Preskočite na sadržaj
Povratak na Nymbot

Baza znanja Razvijači

Ravnoteža, top-up i ključevi

Provjerite što imate, nadogradite se preko Lightning-a, nadogradite se automatski iz vlastitog novčanika, vidite koliko košta svaki zahtjev i upravljajte ključima iz koda.

Proverite ravnotežu

Oba vaša bilance, i koliko je kape ovog ključa se koristi.

GET https://nymbot.ai/api/v1/credits/balance Potreban vam je API ključ. POST Radi i za kupce koji to očekuju.

balance je dva salda zajedno u dolarima po trenutnoj ceni Bitcoina, za alate koji očekuju jedan broj (null ako se cijena ne može pročitati). ostatak je u kreditima i ratama, što je način na koji se ravnoteže zapravo drže. key opisuje ključ koji je zatražen. ključ koji je dostigao svoj limit još uvijek može provjeriti ravnotežu.

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"
  }
}
StatusKada
401Ključ je nedostajao, nepoznat, opozvan ili istekao.

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ćanja

Kako možete popuniti, i granice. munja je jedina metoda.

GET https://nymbot.ai/api/v1/topup/payment-methods Nije potreban ključ.

Top-up je 10 do 1.000.000 sats; Pro top-up mora kupiti barem jedan Pro kredit, tako da počinje na 100 sats. bulk_bonus navodi dodatni kredit na većim top-upovima, isti kao u aplikaciji: 10%, 15% ili 20% više na standardnim top-upima od 500, 1.000 ili 5.000 sats, i na Pro top-upima od 5.000, 10.000 ili 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);

Uspon preko munje

Napravlja Lightning račun koji dodaje kredit na nym ključ pripada. Plaća ga iz bilo koje Lightning novčanik, a zatim Proverite ga Da biste dobili dodatni kredit.

POST https://nymbot.ai/api/v1/topup/create/btc-lightning Potreban vam je API ključ.

PoljeVrstePotrebnoOpis
amountBrojDaKoliko je, u currencyCijeli broj za sats.
currencyStrukturaNeSATS (u slučaju neispunjavanja obaveza), USD ili BTCDolar se pretvara po trenutnoj ceni Bitcoina.
tierStrukturaNepro (u slučaju neispunjenja obaveza) ili standard: u koju ravnotežu ide kredit.

Standardni kredit je 10 sats i Pro kredit 100 sats, plus bilo koji masovni bonus; credits kaže šta će ovaj račun dodati.

Odgovor

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "payment_request": "lnbc100u1p5...",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": "2026-09-30T09:27:00Z",
  "status": "pending"
}
StatusKada
400Druga metoda na putu (unsupported_method), nepoznata valuta (unsupported_currency) ili tier, manji iznos, ili iznos ispod minimalnog (amount_too_small), preko 1 000 000 sats (amount_too_large) ili odbijen od strane Lightning novčanika (amount_out_of_range).
429Više od 60 faktura za ovaj nimm, ili 120 sa ove adrese, u satu (rate_limit_exceeded, sa Retry-After).
502U ovom trenutku nije moguće izraditi račun (invoice_unavailable, sa 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);

Provjerite top-up

Pita da li je faktura plaćena i, kada je, dodaje kredit. Provjera je ono što je kredit, tako da nakon plaćanja, provjerite dok status nije creditedProvjeravanje ponovo nakon toga je sigurno: kredit se sleti jednom, bez obzira na to koliko puta tražite.

GET https://nymbot.ai/api/v1/topup/status/{invoice_id} - treba ključ od nim koji je napravio fakturu.

status je pending (Još uvek nije plaćena) paid (plaćen, ali još nije kreditiran; provjerite ponovo), credited (na vašoj ravnoteži) ili expired (ne plaća se na vrijeme). Polja bilance su za razinu na kojoj se računi vrše.

Odgovor

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "status": "credited",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": null,
  "balance_credits": 523.33,
  "balance_sats": 52333
}
StatusKada
400ID nije 64-karakterski id iz poziva za kreiranje.
404Nema računa za taj id za vaš nim (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);

Želite istoriju

Jedan red po zahtjevu: šta je to bilo, koji model, koliko tokena i koliko košta. Ne zadržavaju se upite ili odgovori, tako da se nijedan ne vraća. Redovi se čuvaju 90 dana, najnovije prvo. Ključ koji je dostigao svoju granicu još uvijek može pročitati svoju istoriju.

GET https://nymbot.ai/api/v1/queries/history — treba API ključ, koji vidi vlastite zahteve, ili Potpisani zahtev od vašeg nim, koji vidi svaki ključ.

PoljeVrstePotrebnoOpis
pageUslovi korišćenja (query)NePodrazumevano 1, najviše 1000; viša stranica je 400 invalid_value.
page_countUslovi korišćenja (query)NeRedovi po stranici. Podrazumevano 20, najviše 100.
start_date
end_date
String (preuzimanje pitanja)NeISO 8601 datumi ili vremena.
modelString (preuzimanje pitanja)NeSamo ovaj model.
typeString (preuzimanje pitanja)Nechat, responses, messages, image, video, speech, transcription ili embedding.
all_keysUslovi korišćenja (query)NeUz jedan ključ: true uključuje svaki ključ istog nym. podrazumevano false.
key_idString (preuzimanje pitanja)NeUz potpisan zahtjev, ili all_keys=trueSamo ovaj 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);

Potpisivanje zahteva za račun

Stvaranje, promjena i opoziv ključeva, sažetak računa i automatski top-up ne uzimaju API ključ. Oni uzimaju potpis od vašeg nym, tako da ispušten ključ može potrošiti do svoje kapije, ali nikada ne može napraviti drugi ključ ili podići svoj kapije.

Aplikacija radi ovo za vas: sve u svom vatra Ovaj odjeljak je potreban samo da biste upravljali ključima iz vlastitog koda.

Potpis je Nostr događaj vrste 27235 (NIP-98), poslan baz64-kodiran u Authorization Header sa rečju Nostr Na prednjem delu:

događaj

{
  "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 je potpuni URL zahtjeva, uključujući niz upita, tačno kao što je poslan.
  • method To je HTTP metoda.
  • payload je SHA-256 sirovog zahteva tijela, u hex. POST i PATCH, a tijelo koje šaljete mora biti bajt za bajt ono što ste hashed.
  • created_at mora biti u roku od 60 sekundi od sata servera.
  • Svaki događaj radi jednom, a GET uključen, tako da se zabeležena glava ne može ponovo igrati. Potpišite novu za svaki zahtev. nonce Tag sa slučajnom vrijednošću tako da se dva zahteva potpisana u istoj sekundi i dalje razlikuju.
  • Tijelo potpisanog zahtjeva može biti najviše 64 KB, a tijelo treba Content-Type: application/json.

Nedostajući događaj se vraća 401 missing_nostr_auth; jedan koji je loše formiran, loše potpisan, previše star, ili za drugačiji URL, metod ili tijelo vraća invalid_nostr_auth, s razlogom u poruci; ponovno korišten jedan vraća nostr_auth_replayedPotpis se provjerava pre nego što se tijelo pročita, a svaka adresa može da ga ne uspije 30 puta u minuti (IPv6 adresa se računa kao cijela /64); nakon toga dobija 429 sa Retry-After.

Pregledači mogu pozvati ove krajnje tačke samo sa Nymbotovih sopstvenih stranica (https://nymbot.ai, https://nymchat.app Stranica na bilo kojoj drugoj stranici ne dobija CORS glave natrag, tako da ne može pročitati ono što vraćaju. OriginOni nisu pogođeni.

Vaš tajni ključ

Potpisivanje treba tajni ključ vašeg nyma (na nsec), koji kontrolira sve: vaš identitet, vašu istoriju i vašu bilancu. Samo ga stavite u skript na mašini kojoj verujete, pročitajte ga iz okoline umjesto da ga napišete u datoteku, i preferirajte aplikaciju kada možete.

Ovi pomoćnici grade glavu. Kasniji primjeri na ovoj stranici koriste ih. Oni čitaju tajni ključ u šestom redu iz NOSTR_SECRET_HEX; cURL jedan koristi Neki alat za komandnu liniju, koji uzima nsec ili hex ključ, i 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");
}

Sažetak računa

Šta API list aplikacije prikazuje na vrhu: vaš javni ključ, oba balansira, koliko ključeva je aktivno (nije opozvano ili je istekao), i Automatski top-up postavljanje, ili null kada ih server ne nudi.

GET https://nymbot.ai/api/v1/account Potrebno je a Potpisani zahtev.

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čima

Krajnje tačke iza liste ključa aplikacije. Svi oni trebaju Potpisani zahtevSvaki ključ se vraća u ovom obrascu, sa vremenima u ISO 8601 i iznosima u sats:

Ključni objekti

{
  "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 dovoljno da prepoznate ključ, ali ne i da ga koristite, a sam ključ se vraća samo jednom, kada je napravljen.

Ključne reči

GET https://nymbot.ai/api/v1/keys Potpisan je.

PoljeVrstePotrebnoOpis
include_revokedUslovi korišćenja (query)NeUključuje poništene ključeve. podrazumevano 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);

Stvaranje ključa

POST https://nymbot.ai/api/v1/keys Povratak - povratak 201.

PoljeVrstePotrebnoOpis
nameStrukturaDa1 do 40 znakova, različiti od vaših drugih aktivnih ključeva (ignoring slučaj).
limit_satsIntegracijaNePotrošnja kap u sats, najmanje 1. ostavite ga bez kap.
reset_periodStrukturaNedaily, weekly ili monthlyPotrebe limit_satsOstavite ga za kapu koja se nikada ne ponavlja.
expire_atString ili integerNeKada ključ prestane raditi: ISO 8601 puta, ili milisekundama od 1970.

Odgovor na pitanje (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"
  }
}
StatusKada
400Nedostatak ili previše dugo ime; ime već u upotrebi (duplicate_name); cap koji nije čitav broj od najmanje 1; reset period bez cap; istek u prošlosti; nepoznato polje (unknown_parameter); ili 25 aktivnih ključeva već (too_many_keys).
429Više od 60 ključeva napravljenih ovom nimom, ili 120 od ove adrese, u satu (rate_limit_exceeded, sa 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);

Čitanje jednog ključa

GET https://nymbot.ai/api/v1/keys/{id} Potpisan je.

Povratak {"data": {…}} sa ključnim predmetom, ili 404 key_not_found ako vaš ključ nema taj id.

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);

Promena ključa

PATCH https://nymbot.ai/api/v1/keys/{id} Potpisan je.

Pošaljite bilo koju name, limit_sats, reset_period i expire_at, sa istim pravilima kao i prilikom pravljenja ključa. null Izbriše polje: nema ograničenja, nema resetovanja, nema isteka. Promjena perioda resetovanja započinje novi period na nuli.400 key_revoked• Povratak {"data": {…}} sa ažuriranim ključnim objektom.

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);

Otkazivanje ključa

DELETE https://nymbot.ai/api/v1/keys/{id} Potpisan je.

Zaustavlja ključ odjednom, za dobro. ostaje na listi sa revoked_at postavljen, a može se vidjeti sa include_revoked=truePovlačenje ključa koji je već povučen odgovara na isti način. Samo se zadržava 50 najnovijih povučenih ključa; stariji ključi se brišu kada se povuče drugi 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 auto-top-up uređaji

Povežite Lightning novčanik sa Nostr Wallet Connect i Nymbot samostalno podiže ravnotežu kada troškovi API-ja budu niski. API list aplikacije ima iste postavke; to su krajnje točke iza njega. Potpisani zahtev.

Kako to funkcioniše: nakon što se API zahtjev naplaćuje na saldo koji ste odabrali da gledate, ako je taj saldo pao ispod vašeg praga, Nymbot napravi fakturu za vaš top-up iznos, traži od vašeg novčanika da ga plati i dodaje kredit. To se popne najviše jednom svakih 5 minuta za svaki nym i saldo, tako da izbijanje zahteva ne može isprazniti novčanik. Trošenje u aplikacijama ga ne pokreće. Vrijeme i veličina posljednjeg top-up, i posljednja greška, su u postavkama; ako je plaćanje prošlo nakon greške, provjerite njegovu fakturu sa Top-up situacija Krediti za to.

Prije nego što povežete novčanik

Nymbot ga skladišti šifrovanim i samo ga koristi za plaćanje vlastitih računa, ali napravite vezu samo za to, sa budžetom za potrošnju u novčaniku, tako da je najviše što bi ikada moglo platiti broj koji ste odabrali. pay_invoice.

Povezivanje novčanika

POST https://nymbot.ai/api/v1/nwc-auto-topup/connect Potpisan je.

PoljeVrstePotrebnoOpis
nwc_urlStrukturaDaStruktura poveznice, početak nostr+walletconnect://Nymbot traži novčanik za get_info prije nego što ga sačuvate, a skladišti ga šifrirano.
threshold_satsIntegracijaDaTop up kada ravnoteža padne ispod ovih mnogo sats.
topup_satsIntegracijaDaKoliko da dodam svaki put. 1000 do 1.000.000 sats.
tierStrukturaNepro (u slučaju neispunjenja obaveza) ili standard: ravnoteža za gledanje i top up.

Odgovor

{
  "data": {
    "connected": true,
    "threshold_sats": 5000,
    "topup_sats": 20000,
    "tier": "pro",
    "last_topup_at": null,
    "last_topup_sats": null,
    "last_error": null
  }
}
StatusKada
400nije povezan sa mrežnom mrežom (invalid_nwc_url); novčanik nije odgovorio na svoj relej (nwc_unreachable) ili odbio kontrolu (nwc_rejected); veza ne može platiti račune (nwc_missing_permission); ili iznos izvan granica.
501Auto-top-up nije uključen za ovaj server (nwc_unavailableIsto vrijedi i za druge dvije krajnje točke.

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());

Čitanje postavki

GET https://nymbot.ai/api/v1/nwc-auto-topup Potpisan je.

Vraća isti objekt kao povezivanje, sa connected: false i ostala polja null kada nema povezanog novčanika. Sam lanac veze se nikada ne vraća.

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());

Isključivanje

DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection Potpisan je.

Brisanje skladištenog niza veza. Ne kreira se više top-up. Da biste bili sigurni, takođe možete opozvati vezu u novčaniku.

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ćanje po zahtevu bez ključa

Krajnje točke fiksne cene mogu se platiti za jedan zahtev u jednom trenutku preko Lightning-a, bez ključa, bez računa i bez salda: POST /images/generations, POST /images/edits, POST /videos, POST /audio/speech, POST /audio/transcriptions, POST /audio/translations i POST /embeddingsChat, odgovori i poruke uvek trebaju ključ.Zahtjev koji nosi ključ obračunava se na saldo kao i obično; tok plaćanja počinje samo kada nije poslan ključ.

Nymbot govori dve verzije iste ideje, iz jednog backend: Lightning Labs' Struktura402 (takođe prihvaćen pod svojim starim imenom, LSAT) i nacrta IETF Plaćanje HTTP autentifikacioni sistem sa lightning Metoda i charge Koristite ono što vaš kupac razumije.

Vođenje sopstvenog servera

Plaćanje bez ključa je uključeno samo kada API_L402_SECRET sadrži najmanje 32 slučajne bajte, kao što su hex (64 znakova) ili base64 (44). openssl rand -hex 32Kratka ili nagađajuća vrijednost isključuje funkciju i bilježi zašto. API_L402_SECRET_PREVIOUS za jedan dan: akreditacije, status URL-ovi i izazovi pod njim nastaviti raditi dok ne istekne.

izazov

Pošaljite zahtjev sa ne Authorization ako je važeća, ništa ne radi, a dobijate 402 Payment Required sa fakturom za točno ono što traži troškove: istu cenu ključ bi platio, pretvoren u 10 sats standardni kredit ili 100 sats Pro kredit i zaokružen na cijeli sat (najmanje 1 sat, a najmanje 0.05 kredit minimum). WWW-Authenticate izazovi za istu fakturu:

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ćanje request parametar je base64url JSON: {"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.

Izazov je vezan za krajnju tačku, za Content-Type (njegova vrsta medija i, za više dijelova, njegova granica) i na SHA-256 tačnog tela bajtova koje ste poslali, i traje 15 minuta. identične Ponovno upućivanje: isto Content-Type i iste JSON bajte, ili za višestruke krajnje tačke (/images/edits, /audio/transcriptions, /audio/translationsVećina HTTP biblioteka odabire novu granicu svaki put kada kodiraju obrazac, pa ga kodirajte jednom i pošaljite te bajte dva puta.

Svaka adresa može zatražiti 30 izazova po minuti (IPv6 adresa se računa kao cijela /64). Zahtjevi čija adresa nije poznata dijele strože 10 po minuti, i postoji ukupni limit na izazove Nymbot problema u svim adresama; zahtjev odbijen pre nego što je izazov napravljen (na primjer, sa tijelom koji nije valjan JSON) ne računa prema njemu. 429 sa Retry-AfterPlaćene krajnje točke poziva bez ključa ili povjerenja takođe se računaju prema općem ograničenju od 120 neautentificiranih zahtjeva po minuti po adresi. Content-Type nije application/json ili multipart/form-data za upload) je odbijen sa 415 i nikada ne dobija račun.

Ugradnje su cijenjene na osnovu procjene tokena u ulazu, sa marginom od 1,5 puta, budući da je stvarni broj poznat tek nakon toga. Povratak tokena.

Slanje plaćanja

Plaćanje računa sa bilo koji Lightning novčanik. Novčanik vam daje predobrazbu, 64 šezdeset znakova. Zatim pošaljite isti zahtjev s jednim od ovih:

ŠemeGlavni
Struktura402Authorization: L402 <macaroon>:<preimage> (LSAT takođe radi)
PlaćanjeAuthorization: Payment <base64url JSON>, gde je JSON {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}}

Plaćen zahtjev odgovara baš kao onaj koji je napravljen s ključem, osim da je nymbot objekat nema polja ravnoteže: {"payment": "l402", "tier": "pro", "paid_sats": 237, "charged_sats": 237}, a ne postoji X-Nymbot-Balance-Sats Zahtjev koji se plaća pomoću sheme plaćanja dobija i Payment-Receipt glava (base64url JSON sa id izazova, hash plaćanja kao reference, status i timestampPlaćeni upiti nisu vezani za nijedan nim, tako da se ne pojavljuju u istoriji upita.

StatusKada
402 payment_already_usedSvaki plaćanje plaća za jedan zahtev. odgovor je novi izazov za ovaj zahtev, tako da klijent koji cache svoje posljednje povjerljivosti (kao lnget Da) jednostavno zemlja opet.
402 payment_mismatchKredencijal je izdan za drugu krajnju točku, Content-Type ili tijelo, ili plaća manje nego što ovaj zahtjev sada košta. Novi izazov za ovaj zahtev dolazi s njim; ako je plaćanje bilo premalo, ono što ste platili vraća se kao Povratak tokena (refund_token i refund_sats u svom telu).
402 payment_expiredViše od 15 minuta je prošlo od izazova. Novi izazov dolazi s njim. Ako predobraza pokazuje da ste platili, ono što ste platili vraća se kao Povratak tokena (refund_token i refund_sats u tijelu), jednom; tada se kredencijal iskoristi.
401 invalid_preimagePreobrazba ne hash računa plaćanja hash. plaćanje se ne koristi.
401 invalid_payment_credentialPovjerljivost je deformirana, promijenjena nakon što ju je izdao Nymbot, ili imena za plaćanje za koje Nymbot nikada nije izdao fakturu.
429 rate_limit_exceededViše od 30 akreditacija ili ključeva koji nisu bili verifikovani došli su s ove adrese u minuti, ili je jedan token za vraćanje poslao više od 60 puta u 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"));

Klijenti su izgrađeni na mppx sa Metoda munje rukovati izazov plaćanja sami; Pokaži ih na krajnju tačku i pusti ih da plate.

Video snimci

Plaćanje POST /videos Odgovori 202 kao ključ jedan, plus a status_url: GET bez ikakvog ključa za praćenje posla. Potpisan je i radi 24 sata, sve dok se posao drži.

{
  "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..."
  }
}

Održavajte refund_token od ovog odgovora: to je prikazano samo ovdje. To je prazno dok video prikazuje (GET /api/v1/l402/refunds Odgovori "status": "pending"); ako se render ne napravi bez računa, plaćanje će sletjeti na njega. refund_sats za vraćeni posao, ali nikada žeton, tako da dijeljenje statusa URL-a ne dijeli povrat.

Povratak

Ako plaćeni zahtjev ne uspije i davatelj je naplaćivao Nymbot za pokušaj, plaćanje se zadržava i greška kaže da je tako, sa charged_sats, baš kao i kod ključanog zahtjeva. Ako ne uspije bez obračuna, greška nosi Povratak tokena Vredi ono što ste platili:

{
  "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"
  }
}

Neiskorišćeni dijelovi se vraćaju na isti način: ako ste zatražili dvije slike, a jedna nije bila obračunata, odgovor je uspješan. nymbot objekt nosi token za povrat novca za nedostajući; transkripcija čija se dužina ne može pročitati unaprijed je cijenjena za najduže što datoteka može biti (nikada više od 30 minuta), a razlika do stvarne dužine vraća se kao token za povrat novca; ako se ispostavi da je duža od 30 minuta, to se odbija sa 413 i cela isplata se vraća. Ugradnje vraćaju ono što je procjena zadržala. Neuspjeli video vraća token njegovu podnesku vratio.

Token za povrat novca je slučajni 256-bitni kod. Nymbot pohranjuje samo svoj haš, a isteče nakon 30 dana.

  • Plaćajte s njim. Pošaljite Authorization: Bearer REFUND-… U svakom slučaju, potrebno je imati na umu da je to jedan od najvažnijih faktora koji se odnose na ljudsko zdravlje, a koji se odnosi na zdravlje ljudi (refund_token_sats U ovom nymbot objekat). žeton vrijedi manje od odgovora na upit 402 refund_insufficient; neispravan neuspjeh stavlja sats natrag na isti token.
  • Provjerite ga. GET /api/v1/l402/refunds Isti header se vraća {"sats": 237, "status": "open", "expires_at": "..."}.
  • Jedan token može se koristiti najviše 60 puta u minuti.
  • Premjestite ga u nym. Stavite ga u Oporavak poklona u aplikaciji Nymbot, ili pozovite POST /api/v1/l402/refunds/redeem sa a Potpisani zahtev i {"refund_token": "REFUND-...", "balance": "standard"} ili "pro"Cijeli krediti idu na ravnotežu (10 sats svaki na standard, 100 na Pro); sats koji ne čine čitav kredit ostaje na žetonu za API zahteve.

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 } }