Kennisbasis Ontwikkelaar
Balans, top-ups en sleutels
Kyk wat jy het, top-up oor Lightning, top-up outomaties van jou eie portemonnee, sien wat elke versoek kos, en bestuur sleutels uit kode.
Hierdie bladsy is gerieflikheidshalwe masjienvertaal. Die Engelse oorspronklike is die weergawe wat van toepassing is.
Kyk na die balans
Beide van jou salarisse, en hoeveel van hierdie sleutel se cap gebruik word.
GET https://nymbot.ai/api/v1/credits/balance Jy het 'n API sleutel nodig. POST Dit werk ook vir kliënte wat dit verwag.
balance is die twee salde saam in dollars by die huidige Bitcoin prys, vir gereedskap wat 'n enkele getal verwag (null Die res is in krediete en sats, wat is hoe die salde eintlik gehou word. key 'N sleutel wat sy cap bereik het, kan steeds die balans kyk.
Reaksies
{
"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"
}
}
| Status | Wanneer |
|---|---|
401 | Die sleutel is ontbreek, onbekend, herroep of verval. |
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);
Betaalmetodes
Hoe jy kan top-up, en die limiete. Lightning is die enigste metode.
GET https://nymbot.ai/api/v1/topup/payment-methods Geen sleutel nodig nie.
'N Top-up is 10 tot 1.000.000 sats; 'n Pro-top-up moet ten minste een Pro-krediet koop, dus dit begin by 100 sats. bulk_bonus die ekstra krediet op groter top-ups, dieselfde as in die app: 10%, 15% of 20% meer op standaard top-ups van 500, 1.000 of 5.000 sats, en op Pro top-ups van 5.000, 10.000 of 50.000 sats.
Reaksies
{
"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);
Opstaan oor die bliksem
Maak 'n Lightning-rekening wat krediet byvoeg aan die nym waaraan die sleutel behoort. Kyk dit Om die krediet toe te voeg.
POST https://nymbot.ai/api/v1/topup/create/btc-lightning Jy het 'n API sleutel nodig.
| Die veld | Die tipe | vereis | Beskrywing |
|---|---|---|---|
amount | Die nommer | Ja | Hoeveel, in currency'N hele getal vir die sats. |
currency | String | nie | SATS die vervalsing, USD of BTCDollars word omskep by die huidige Bitcoin prys. |
tier | String | nie | pro (die verval) of standard: watter balans die krediet gaan. |
'N Standaard krediet is 10 sats en 'n Pro krediet 100 sats, plus enige bulk bonus;
credits sê wat hierdie rekening sal byvoeg.
Reaksies
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"payment_request": "lnbc100u1p5...",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": "2026-09-30T09:27:00Z",
"status": "pending"
}
| Status | Wanneer |
|---|---|
400 | Nog 'n metode in die pad (unsupported_method, 'n onbekende geldeenheid (unsupported_currency) of tier, 'n ontbrekende bedrag, of 'n bedrag onder die minimum (amount_too_smallMeer as 1 000 000 (amount_too_large) of verwerp deur die Lightning portemonnee (amount_out_of_range). |
429 | Meer as 60 fakture vir hierdie nym, of 120 van hierdie adres, in 'n uur (rate_limit_exceeded, met Retry-After). |
502 | Geen rekening kan op die oomblik gemaak word nie (invoice_unavailable, met 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);
Kyk na 'n top-up
Vra of die rekening betaal is en, sodra dit het, voeg die krediet by. Check is wat dit krediet, so na betaling, kyk totdat die status is creditedKyk daarna weer is veilig: die krediet land een keer, maak nie saak hoeveel keer jy vra nie.
GET https://nymbot.ai/api/v1/topup/status/{invoice_id} - benodig 'n sleutel van die nym wat die faktuur gemaak het.
status is pending (Ek het nog nie betaal nie) paid (Betal, maar nog nie gekrediteer nie; kyk weer), credited (op jou balans) of expired (nie tydelik betaal nie). Die balansvelde is vir die vlak waarop die faktuur boonste is.
Reaksies
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"status": "credited",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": null,
"balance_credits": 523.33,
"balance_sats": 52333
}
| Status | Wanneer |
|---|---|
400 | Die id is nie die 64-karakter id van die skep oproep nie. |
404 | Geen rekening deur daardie id vir jou 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);
Historie wil hê
Een rigting per versoek: wat dit was, watter model, hoeveel tokens en wat dit kos. Geen oproepe of antwoorde word bewaar nie, sodat geen teruggekeer word nie. Rigtings word vir 90 dae bewaar, die nuutste eerste. 'N sleutel wat sy cap bereik het, kan nog steeds sy geskiedenis lees.
GET https://nymbot.ai/api/v1/queries/history — benodig 'n API sleutel, wat sy eie versoekings sien, of 'n Onderteken verzoek van jou nim, wat elke sleutel sien.
| Die veld | Die tipe | vereis | Beskrywing |
|---|---|---|---|
page | Integrasie van die vraag (query) | nie | Standaard 1, ten hoogste 1000; 'n hoër bladsy is 400 invalid_value. |
page_count | Integrasie van die vraag (query) | nie | Rooi per bladsy. Standaard 20, met 'n maksimum van 100. |
start_dateend_date | Die vraag (query) | nie | ISO 8601 datum of tyd. |
model | Die vraag (query) | nie | Net hierdie model. |
type | Die vraag (query) | nie | chat, responses, messages, image, video, speech, transcription of embedding. |
all_keys | Die Booleaanse (Query) | nie | Met ’n sleutel: true bevat elke sleutel van dieselfde nym. false. |
key_id | Die vraag (query) | nie | Met 'n ondertekende versoek, of met all_keys=trueAlleen die sleutel. |
Reaksies
{
"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);
Handtekening van rekeningverzoeke
Maak, verander en herroep sleutels, die rekeningopsomming en outomatiese top-ups neem nie 'n API sleutel nie. Hulle neem 'n handtekening van jou nym, sodat 'n lekkie sleutel tot sy cap kan spandeer, maar kan nooit 'n ander sleutel maak of sy eie cap verhoog nie.
Die app doen dit vir jou: alles in sy vuur die sheet gebruik hierdie eindpunte. Jy benodig hierdie afdeling net om sleutels uit jou eie kode te bestuur.
Die handtekening is 'n Nostr-gebeurtenis van soort 27235 (NIP-98), gestuur base64-gekodeer in die
Authorization Header met die woord Nostr In die voorkant:
Die gebeurtenis
{
"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": "..."
}
uis die volledige URL van die versoek, query string ingesluit, presies soos gestuur.methodDit is die HTTP metode.payloadis die SHA-256 van die ruwe versoek lichaam, in hex.POSTenPATCH, en die liggaam wat jy stuur, moet byte vir byte wees wat jy hash het.created_atDit moet binne 60 sekondes van die bediener se klok wees.- Elke gebeurtenis werk een keer, a
GETingesluit, sodat 'n opgeneem kop nie weer gespeel kan word nie. Sluit 'n nuwe kop vir elke versoek. Voeg 'nnoncetag met 'n ewekansige waarde sodat twee versoekings wat in dieselfde sekonde onderteken is, steeds verskillend is. - Die liggaam van 'n ondertekente versoek kan maksimum 64 KB wees, en 'n liggaam benodig
Content-Type: application/json.
'n Vermiste gebeurtenis terugkeer 401 missing_nostr_auth; een wat slegs gevorm is, slegs onderteken, te oud, of vir 'n ander URL, metode of liggaam retourneer
invalid_nostr_authmet die rede in die boodskap; 'n hergebruikte een terugkeer
nostr_auth_replayed'N API sleutel wat na hierdie eindpunte gestuur word, word geweier.Die handtekening word gekeken voordat die liggaam gelees word, en elke adres kan dit 30 keer per minuut misluk ('n IPv6 adres tel as sy hele /64); daarna kry dit 429 met
Retry-After.
Browsers kan hierdie eindpunte slegs van Nymbot se eie webwerwe oproep (https://nymbot.ai,
https://nymchat.app 'N bladsy op enige ander webwerf kry geen CORS-kopies terug nie, sodat dit nie kan lees wat hulle terugkeer nie.
OriginHulle word nie beïnvloed nie.
Die handtekening benodig jou nym se geheime sleutel (die nsec), wat alles beheer: jou identiteit, jou geskiedenis en jou balans. Sluit dit net in 'n script op 'n masjien wat jy vertrou, lees dit uit die omgewing eerder as om dit in die lêer te skryf, en verkies die app wanneer jy kan.
Hierdie helpers bou die kop. Die latere voorbeelde op hierdie bladsy gebruik hulle. Hulle lees die geheime sleutel in hex van NOSTR_SECRET_HEX; die cURL een gebruik die
Naak 'n kommando-lyntool, wat 'n nsec of hex sleutel neem, en sha256sum op die 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");
}
Die rekeningversameling
Wat die app se API-blad aan die top wys: jou openbare sleutel, beide balans, hoeveel sleutels aktief is (nie herroep of verval nie), en die Automatiese top-up instellings, of
null wanneer die bediener hulle nie bied nie.
GET https://nymbot.ai/api/v1/account Die behoefte a Onderteken verzoek.
Reaksies
{
"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());
Die bestuur van sleutels
Die eindpunte agter die app se sleutel lys. Almal van hulle benodig 'n Onderteken verzoekElke sleutel word in hierdie vorm teruggegee, met tye in ISO 8601 en bedrag in sats:
Belangrike voorwerp
{
"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 Dit is genoeg om 'n sleutel te herken, maar nie om dit te gebruik nie.
Skryf sleutels
GET https://nymbot.ai/api/v1/keys Ek het onderteken.
| Die veld | Die tipe | vereis | Beskrywing |
|---|---|---|---|
include_revoked | Die Booleaanse (Query) | nie | Inclusief herroepde sleutels. standaard false. |
Reaksies
{ "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);
Maak 'n sleutel
POST https://nymbot.ai/api/v1/keys Geskryf, terugkeer 201.
| Die veld | Die tipe | vereis | Beskrywing |
|---|---|---|---|
name | String | Ja | 1 tot 40 karakters, anders as jou ander aktiewe sleutels (ignoreer geval). |
limit_sats | Integraal | nie | Die besteding cap in sats, ten minste 1. |
reset_period | String | nie | daily, weekly of monthlyDie behoeftes limit_satsLaat dit uit vir 'n hoed wat nooit herstel nie. |
expire_at | String of integer | nie | Wanneer die sleutel ophou werk: 'n ISO 8601 tyd, of millisekondes sedert 1970. |
Die antwoord (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"
}
}
| Status | Wanneer |
|---|---|
400 | 'N Ontbrekende of te lang naam; 'n naam wat reeds gebruik word (duplicate_name); 'n cap wat nie 'n hele getal van ten minste 1 is nie; 'n herstelperiode sonder cap; 'n vervaldatum in die verlede; 'n onbekende veld (unknown_parameter); of 25 aktiewe sleutels reeds (too_many_keys). |
429 | Meer as 60 sleutels gemaak deur hierdie nim, of 120 van hierdie adres, in 'n uur (rate_limit_exceeded, met 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);
Lees 'n sleutel
GET https://nymbot.ai/api/v1/keys/{id} Ek het onderteken.
terugkeer {"data": {…}} met die sleutel voorwerp, of 404
key_not_found as geen sleutel van jou die ID het nie.
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);
Verander 'n sleutel
PATCH https://nymbot.ai/api/v1/keys/{id} Ek het onderteken.
Stuur enige name, limit_sats, reset_period en
expire_at, met dieselfde reëls as wanneer jy 'n sleutel maak. null 'n veld verwyder: geen cap, geen reset, geen vervaldatum nie. Die verandering van die resetperiode begin 'n nuwe tydperk by nul. 'n herroepde sleutel kan nie verander word nie (400 key_revoked• Terugkeer
{"data": {…}} met die opgedateerde sleutel voorwerp.
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);
Verwyder 'n sleutel
DELETE https://nymbot.ai/api/v1/keys/{id} Ek het onderteken.
Stop die sleutel dadelik, vir goed. Dit bly in die lys met revoked_at geskep, en kan gesien word met include_revoked=trueDie herroeping van 'n sleutel wat reeds herroep is, antwoord op dieselfde manier.Slegs die nuutste 50 herroepte sleutels word bewaar; ouer sleutels word verwyder wanneer 'n ander sleutel herroep word.
Reaksies
{ "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());
Die NWC-auto-top-up
Sluit 'n Lightning-beursie met Nostr Wallet Connect en Nymbot sal 'n balans op hulleself opstel wanneer API-uitgawes dit laai. Onderteken verzoek.
Hoe dit werk: Nadat 'n API-verzoek op die saldo gekry word wat jy gekies het om te kyk, as daardie saldo onder jou drempel gedaal het, maak Nymbot 'n faktuur vir jou top-up bedrag, vra jou portemonnee om dit te betaal, en voeg die krediet by. Dit klop maximaal een keer elke 5 minute vir elke nym en saldo, sodat 'n uitbarsting van versoekings die portemonnee nie kan verdraai nie. Spandeer in die programme veroorsaak dit nie. Die tyd en grootte van die laaste top-up, en die laaste fout, is in die instellings; as 'n betaling na 'n fout gegaan het, kyk sy faktuur met Die top-up status krediet daarvoor.
Nymbot stoor dit versleuteld en gebruik dit slegs om sy eie top-up fakture te betaal, maar maak 'n verbinding net vir hierdie, met 'n uitgawesbegroting in jou portemonnee, sodat die meeste wat dit ooit kon betaal, is 'n nommer wat jy gekies het. pay_invoice.
Die verbinding van 'n portemonnee
POST https://nymbot.ai/api/v1/nwc-auto-topup/connect Ek het onderteken.
| Die veld | Die tipe | vereis | Beskrywing |
|---|---|---|---|
nwc_url | String | Ja | Die verbinding string, begin nostr+walletconnect://Nymbot vra die portemonnee vir get_info Voordat jy dit opslaan, en stoor dit versleutel. |
threshold_sats | Integraal | Ja | Top op wanneer die balans onder hierdie baie sats val. Ten minste 1000. |
topup_sats | Integraal | Ja | Hoeveel om elke keer by te voeg. 1000 tot 1.000.000 sats. |
tier | String | nie | pro (die verval) of standard: die balans om te kyk en top op. |
Reaksies
{
"data": {
"connected": true,
"threshold_sats": 5000,
"topup_sats": 20000,
"tier": "pro",
"last_topup_at": null,
"last_topup_sats": null,
"last_error": null
}
}
| Status | Wanneer |
|---|---|
400 | Nie 'n koppelvlak nie (invalid_nwc_url(Hulle het nie ’n antwoord op die boodskap nie.)nwc_unreachable) of verwerp die toets (nwc_rejected); die verbinding kan nie rekeninge betaal nie (nwc_missing_permission); of 'n bedrag buite die limiete. |
501 | Dit is nie nodig om die rekenaar te verwyder nie (nwc_unavailableDieselfde geld vir die ander twee eindpunte. |
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());
Lees die instellings
GET https://nymbot.ai/api/v1/nwc-auto-topup Ek het onderteken.
Gee dieselfde voorwerp as die verbinding, met connected: false En die ander velde
null wanneer geen portemonnee verbind word nie. Die verbindingsreeks self word nooit teruggestuur nie.
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());
Ontkoppeling
DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection Ek het onderteken.
Verwyder die opgeslagen verbindingsreeks. Geen meer top-ups word gemaak nie. Om seker te wees, kan jy ook die verbinding in jou portemonnee herroep.
Reaksies
{ "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());
Betaal per versoek sonder sleutel
Die vaste-prys eindpunte kan betaal word vir een versoek per tyd oor Lightning, sonder sleutel, geen rekening en geen saldo: POST /images/generations, POST /images/edits,
POST /videos, POST /audio/speech, POST /audio/transcriptions,
POST /audio/translations en POST /embeddingsChat, antwoorde en boodskappe benodig altyd 'n sleutel. 'N Verzoek wat 'n sleutel dra, word soos gewoonlik in rekening geneem; die betalingstroom begin slegs wanneer geen sleutel gestuur word nie.
Nymbot praat twee weergawes van dieselfde idee, van een backend: Lightning Labs'
Die L402 (Ook aanvaar onder sy ou naam, LSAT(en die IETF ontwerp
Betaling HTTP-authentification skema met die lightning Die metode en
charge Gebruik wat jou kliënt verstaan.
Betaal sonder 'n sleutel is slegs aan wanneer API_L402_SECRET bevat ten minste 32 ewekansige bytes, soos hex (64 karakters) of base64 (44). openssl rand -hex 32'N Korter of vermoedbare waarde sluit die funksie uit en log waarom. API_L402_SECRET_PREVIOUS vir 'n dag: credentials, status URL's en uitdagings wat onder dit gemaak word, werk totdat hulle verval.
Die uitdaging
Stuur die versoek met nie Authorization header. As dit geldig is, loop niks, en jy kry 402 Payment Required met 'n faktuur vir presies wat die versoek koste: dieselfde prys wat 'n sleutel sou betaal, omskep by 10 sats 'n standaard krediet of 100 sats 'n Pro krediet en afgerond tot 'n hele sat (ten minste 1 sat, en ten minste 0.05 krediet minimum). WWW-Authenticate uitdagings vir dieselfde rekening:
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 }
}
Die betaling request Die parameter is base64url JSON:
{"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.
'N Uitdaging is gebind aan die eindpunt, aan die Content-Type (sy media tipe en, vir multipart, sy grens) en na die SHA-256 van die presiese liggaam bytes wat jy gestuur het, en duur 15 minute. Identiese Nog 'n vraag: dieselfde
Content-Type en dieselfde JSON bytes, of vir die multipart eindpunte (/images/edits, /audio/transcriptions, /audio/translationsDie meeste HTTP biblioteke kies 'n nuwe grens elke keer as hulle 'n vorm kodeer, so kodeer dit een keer en stuur daardie bytes twee keer.
Elke adres kan vra vir 30 uitdagings per minuut ('n IPv6 adres tel as sy hele /64). Versoekings wie se adres nie bekend is deel 'n strenger 10 per minuut, en daar is 'n algehele cap op die uitdagings Nymbot probleme oor al die adresse; 'n versoek verwerp voordat 'n uitdaging gemaak word (byvoorbeeld met 'n liggaam wat nie geldig is JSON) tel nie teenoor dit. 429 met Retry-AfterBetaalde eindpunte wat sonder 'n sleutel of credential geroep word, tel ook tot die algemene limiet van 120 nie-authenticeerde versoekings per minuut per adres. Content-Type is nie application/json (en die
multipart/form-data vir oplaai) word verwerp met 415 en nooit 'n rekening ontvang nie.
Embeddings word geprijs op grond van 'n raming van die tokens in die invoer, met 'n 1.5× marge, aangesien die werklike getal slegs daarna bekend is. Herstel die token.
Stuur die betaling
Betaal die rekening met enige Lightning-beursie. Die beursie gee jou die voorbeeld, 64 hex karakters.
| Skema | Die header |
|---|---|
| Die L402 | Authorization: L402 <macaroon>:<preimage> (LSAT Ek werk ook) |
| Betaling | Authorization: Payment <base64url JSON>waar die JSON is {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}} |
'N Betaalde versoek beantwoord presies soos een wat met 'n sleutel gedoen word, behalwe dat die nymbot
Object het geen balansvelde nie: {"payment": "l402", "tier": "pro", "paid_sats": 237,
"charged_sats": 237}En daar is geen X-Nymbot-Balance-Sats 'N Verzoek wat met die betalingstelsel betaal word, kry ook 'n Payment-Receipt header (base64url JSON met die uitdaging id, die betaling hash as reference, status en
timestampBetaalde versoekings is nie gekoppel aan enige nym nie, dus verskyn hulle nie in die query geskiedenis nie.
| Status | Wanneer |
|---|---|
402 payment_already_used | Elke betaling betaal vir een versoek. Die antwoord is 'n nuwe uitdaging vir hierdie versoek, so 'n kliënt wat sy laaste credential (soos lnget Dit is gewoonlik weer land. |
402 payment_mismatch | Die credential is uitgereik vir 'n ander eindpunt, Content-Type of liggaam, of betaal minder as hierdie versoek nou kos. 'n nuwe uitdaging vir hierdie versoek kom saam met dit; as die betaling te klein was, wat jy betaal, kom terug as 'n Herstel die token (refund_token en refund_sats in die liggaam). |
402 payment_expired | Meer as 15 minute het verby gegaan sedert die uitdaging. 'n Nuwe uitdaging kom saam met dit. As die voorbeeld wys dat jy betaal het, kom wat jy betaal het terug as 'n Herstel die token (refund_token en refund_sats in die liggaam), een keer; die credential word dan uitgeput. |
401 invalid_preimage | Die voorbeeld haas nie op die betaling haas van die faktuur nie. |
401 invalid_payment_credential | Die credential is verkeerd gevorm, is verander nadat Nymbot dit uitgereik het, of name 'n betaling hash Nymbot het nooit 'n faktuur uitgereik nie. 'N macaroon met 'n waarschuwing Nymbot weet nie, of met teenstrydige waarschuwings, word geweier. |
429 rate_limit_exceeded | Meer as 30 credentials of sleutels wat misluk het om te verifieer, het in 'n minuut van hierdie adres gekom, of een terugbetaling token is meer as 60 keer in 'n minuut gestuur. 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"));
Kliënte gebou op mppx met 'n Lightning metode die betaling uitdaging self hanteer; wys hulle op die eindpunt en laat hulle betaal.
Video’s
Die betaalde POST /videos Antwoorde 202 soos 'n sleutel een, plus 'n
status_url: GET dit sonder enige sleutel om die werk te volg. Dit is onderteken en werk vir 24 uur, solank die werk gehou word.
{
"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..."
}
}
Hou die refund_token Dit is nie die enigste ding wat jy kan doen nie, want die video is leeg (GET /api/v1/l402/refunds Antwoorde "status": "pending"); as die render misluk nie, word die betaling daarop geland.
refund_sats vir 'n terugbetaalde werk, maar nooit die token nie, dus deel die status URL deel nie die terugbetaling nie.
Vergoeding
As 'n betaalde versoek misluk en die verskaffer Nymbot vir die poging in rekening geneem het, word die betaling gehou en die fout sê so, met charged_sats, presies soos vir 'n sleutelverzoek. As dit misluk sonder dat dit in rekening geneem word, dra die fout 'n Herstel die token Wat jy betaal:
{
"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"
}
}
Ongebruikte dele kom op dieselfde manier terug: as jy twee foto's gevra het en een mislukte onbetaal, is die sukses van die reaksie nymbot die voorwerp dra 'n terugbetaling token vir die ontbrekende een; 'n transkripsie waarvan die lengte nie voor kan lees word geprys vir die langste die lêer kan wees (nie meer as 30 minute), en die verskil tot die werklike lengte kom terug as 'n terugbetaling token; as dit blyk te wees langer as 30 minute, word dit geweier met 413
en die hele betaling kom terug. Embeddings terug wat die raming teruggehou het. 'n mislukte video terugbetaal die token wat sy inskrywing teruggekeer het.
'N terugbetaling token is 'n ewekansige 256-bits kode. Nymbot stoor slegs sy hash, en dit verval na 30 dae.
- Betaal daarmee. Stuur
Authorization: Bearer REFUND-…Dit is 'n verskil tussen die oorspronklike oorspronklike oorspronklike oorspronklike oorspronklike oorspronklike oorspronklike oorsprong (refund_token_satsIn dienymbot'N Token wat minder waard is as wat die versoek beantwoord402refund_insufficient'N Onbetaalde mislukking plaas die sats terug op dieselfde token. - Controleer dit.
GET /api/v1/l402/refundsmet dieselfde header terugkeer{"sats": 237, "status": "open", "expires_at": "..."}. - Een token kan maximaal 60 keer per minuut gebruik word.
- Beweeg dit na 'n nym. Pas dit in Maak 'n geskenk in die Nymbot-toepassing, of bel
POST /api/v1/l402/refunds/redeemmet a Onderteken verzoek en{"refund_token": "REFUND-...", "balance": "standard"}(en die"pro"Die hele krediete gaan na die balans (10 sats elkeen op standaard, 100 op Pro); sats wat nie 'n hele krediet bly op die token vir API-versoek nie.
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"
Reaksies
{ "data": { "credited": 23, "tier": "standard", "balance_credits": 123, "remaining_sats": 7 } }