Scientia basis Developers
Solvendum, additamenta et claves
Vide quod habes, imple per Lightning, imple automatisme ex proprio portu, vide quidquid quaestio constat, et claves ex codice ger.
Haec pagina machinae ad commodum translata est. Originale Anglicum est versio quae applicatur.
Saldum inspiciens
Utraque saldi tuae, et quanto huius clavis capitis usurpați sunt.
GET https://nymbot.ai/api/v1/credits/balance — clavis API indiget. POST Etiam operatur, clientibus qui id exspectant.
balance suntne duo saldia simul in dollariis pretio Bitcoin praesenti, pro
instrumentis quae unum numerum expectant (null si pretium legi non potest). Reliquum est in
creditis et sats, qua modo saldi re vera conservantur. key Clavem quae petivit describit. Clavis quae finem suum attigit, tamen libram inspicere potest.
Responsio
{
"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 | Quando |
|---|---|
401 | Clavis deest, incognita, abrogata aut expirata est. |
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);
Modi solutionis
Quomodo creditum addere possis, et limites. Lightning est sola ratio.
GET https://nymbot.ai/api/v1/topup/payment-methods — clavis non opus est.
Iniectio est ab 10 ad 1,000,000 sats; iniectio Pro debet saltem unum creditum Pro emere, ergo incipit
ab 100 sats. Limites dollari secundum pretium Bitcoin sequuntur. bulk_bonus creditum additum in maioribus increscentibus enumerat, idem sicut in applicatione: 10%, 15% vel 20% plus in ordinariis increscentibus
ex
500, 1,000 vel 5,000 sats, et in Pro increscentibus ex 5,000, 10,000 vel 50,000 sats.
Responsio
{
"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);
Incredere per Lightning
Facturam Lightning facit quae creditum addit nomini cui clavis pertinet. Ex quacumque portu Lightning eam solva, tunc... probatum vide ut creditum addatur.
POST https://nymbot.ai/api/v1/topup/create/btc-lightning — clavis API indiget.
| Campus | Typus | Necessarium | Descriptio |
|---|---|---|---|
amount | numerus | Ita | Quantum, in currencyNumerus integer pro sats. |
currency | filum | Non | SATS (defaultum), USD aut BTC. Dollarae ex praetio praesenti Bitcoin convertuntur. |
tier | filum | Non | pro (defaultum) an standard: cui saldo creditum pervenit. |
Crēditum ordinārium est 10 sats et crēditum Pro 100 sats, praeter aliquem praemium emptionis in magnā quantitā;
credits dicit quid haec factura addere debeat.
Responsio
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"payment_request": "lnbc100u1p5...",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": "2026-09-30T09:27:00Z",
"status": "pending"
}
| Status | Quando |
|---|---|
400 | Aliter modus in itinere (unsupported_method), numisma incognitum (unsupported_currency) aut gradus, numerus deest, aut numerus sub minimo (amount_too_small), supra 1,000,000 sats (amount_too_large) an ab portu fulgurante recusatum (amount_out_of_range). |
429 | Plus quam sexaginta rationes huius nominis, aut centum viginti ex hoc domicilio, intra horam (*rate_limit_exceeded, cum Retry-After). |
502 | Nullo tempore nunc facturae iniectio potest (invoice_unavailable, cum 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);
Incrémentum praestandum investigans
Rogat an factura soluta sit et, cum soluta erit, creditum addit. Investigatio est quae id credit, itaque post solvendum, investiga donec status sit credited. Iterum inspicere
postea tutum est: creditum semel accidit, quamvisIamcum petas.
GET https://nymbot.ai/api/v1/topup/status/{invoice_id} — claves ab nomine qui rationem reddidit opus habet.
status est pending (nondum solutum), paid (solutum, sed nondum
creditum; iterum inspice), credited (in saldo tuo) an expired (non tempestive solutum). Campi saldos sunt pro gradu cuius factura auget.
Responsio
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"status": "credited",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": null,
"balance_credits": 523.33,
"balance_sats": 52333
}
| Status | Quando |
|---|---|
400 | Id non est id sexaginta quattuor litterarum ex vocatione creationis. |
404 | Nulla factura cum eo nomine pro eo nomine tuo ✉️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);
Historia interrogationum
Una linea per postulationem: quid erat, quae mensura, quot numeri verborum et quid constat. Ne prompta aut responsa servantur, neque reddantur. Lineae per nonaginta dies servantur, novissima primum. Clavis quae finem attigit historiam suam tamen legere potest.
GET https://nymbot.ai/api/v1/queries/history — claves API indiget, quae suas ipsas peticiones videt, aut petitio signata Ex nomine tuo, quod omnis clavis videt.
| Campus | Typus | Necessarium | Descriptio |
|---|---|---|---|
page | numerus integer (quaestio) | Non | Default 1, maxime 1,000; pagina altius est 400 invalid_value. |
page_count | numerus integer (quaestio) | Non | Series per paginam. Default 20, maxime 100. |
start_dateend_date | filum (quaestio) | Non | Tempora vel dies secundum normam ISO 8601. |
model | filum (quaestio) | Non | Solum hoc exemplar. |
type | filum (quaestio) | Non | chat, responses, messages, image, video, speech, transcription aut embedding. |
all_keys | boolean (quaestio) | Non | Cum clave: true omnes claves eiviusdem nominis includit. Default false. |
key_id | filum (quaestio) | Non | Cum petitione signata, vel cum all_keys=true: haec sola clavis. |
Responsio
{
"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);
Petitiones rationum signandae
Claves faciendi, mutandi et revocandi, summa rationis et replenishmentis automatici claves API non accipiunt. Signaturam ex nym vestro accipiunt, itaque clavis effusa usque ad limitem suum adhiberi potest, sed numquam aliam clavem facere vel proprium limitem augere potest.
App haec tibi hoc facit: omnia in loco suo API tabula hos fines utitur. Hanc tantum partem tibi opus est ad claves ex tuo codice regendi.
Signatura est eventus Nostr genus 27235 (NIP-98), in base64 codicibus missus in
Authorization caput cum verbo Nostr ante
Eventus
{
"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": "..."
}
uestne URL integra petitionis, etiam nexus interrogationis inclusa, plane sicut missa.methodmethodus HTTP est.payloadest SHA-256 corporis petendi purissimi, in hex. Opus est inPOSTetPATCH, et corpus quod mittis debet esse byte pro byte idem quem hashisti.created_atintra sexaginta secunda horologii servi intra esse debet.- Omnis eventus semel operatur, a
GETinclusum, ita ut caput captum non possit reperiari. Signum novum pro omni postulatione adde.nonceindex cum valore fortuito signa ut duo petitiones eodem secundo signatae tamen differant. - Corpus rogationis signatae vix 64 KB esse potest, et corpus opus est
Content-Type: application/json.
Eventus amissus redit 401 missing_nostr_auth; quod male constructum, male signatum, nimis vetustum, aut ad aliam URL, methodum, vel corpus, reddit
invalid_nostr_auth, cum ratione in nuntio; res reused redit
nostr_auth_replayed. Clavis API ad has fines mitto recusatur.
Signatura antequam corpus legatur probatur, et omnis locus potest id triginta vices per minutam deficere (adhaerens adnotationem IPv6
tuta numeratur ut tota /64); postea capit 429 cum
Retry-After.
Navigatores hos fines tantum ex ipsis situs Nymbot vocare possunt (https://nymbot.ai,
https://nymchat.app (et subdominia eorum). Pagina in ulla alia pagina nullo CORS
headeribus redditur, ne ea quae reddunt legere possit. Scripta et applicationes nativae, quae nihil mittunt
Origin, non afficiuntur.
Signatio clave secretam pseudonymi tui requirit (id... nsec), quod omnia regit: identitatem tuam, historiam tuam et numerum tuum. Sive in scripto in machina quam fidas pone, e medio ambientis lege potius quam in文件中 scribe, et applicationem praefer si potes.
Hi these adiutores caput aedificant. Exempla posteriora in hac pagina ea utuntur. Clavis secreta in hexus leguntur ex NOSTR_SECRET_HEX; cURL unum utitur
nihil instrumentum lineae imperii, quod clavim nsec vel hex
accipit, et sha256sum (in 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");
}
Summarium rationis
Quod tabula API applicationis in summo ostendit: clavem tuam publicam, utrumque saldo, quot claves sint
activae (non abrogatae vel expiratas), et... repletio automatica configuratio, an
null cum servitor eis non praebet.
GET https://nymbot.ai/api/v1/account — opus est petitio signata.
Responsio
{
"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());
Claves administrando
Terminatio ante listam clavis applicationis. Omnes eae opus habent signatum rogatum. Omnis clavis in hâ formâ redditur, temporibus in ISO 8601 et quantitatibus in sats:
Objectum clavem
{
"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 satis est clavem agnoscere sed non uti. Ipsum clavis solum semel reddeatur, cum fiat.
Claves enumeratio
GET https://nymbot.ai/api/v1/keys — subscriptum.
| Campus | Typus | Necessarium | Descriptio |
|---|---|---|---|
include_revoked | boolean (quaestio) | Non | Clāvēs abrogātās inclūde. Defáltum. false. |
Responsio
{ "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);
Clavem faciens
POST https://nymbot.ai/api/v1/keys — subscriptum. Reditus 201.
| Campus | Typus | Necessarium | Descriptio |
|---|---|---|---|
name | filum | Ita | aI 1 usque ad 40 litterae, diversae a aliis clāvibus tuis activis (non spectantibus casu). |
limit_sats | integer | Non | Limites impensarum in sats, saltem 1. Sine eo si nullum limitis est. |
reset_period | filum | Non | daily, weekly aut monthly. Egestatibus limit_satsRelinque id pro caluto quae numquam renovatur. |
expire_at | series an numerus integer | Non | Cum clavis cessat operari: tempus ISO 8601, vel milliseconda ab anno 1970. |
Responsum (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 | Quando |
|---|---|
400 | Nomen deest vel nimis longum; nomen iam in usu (duplicate_name); limitatio quae non est numerus integer saltem 1; periodus renovationis sine limite; expiratio in praeterito; campus ignotus (unknown_parameter); vel 25 clavis activae iam (too_many_keys). |
429 | Plus quam sexaginta claves ab hoc nomine factae, aut centum viginti ex hac inscriptione, intra horam (rate_limit_exceeded, cum 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);
Legens unum clavis
GET https://nymbot.ai/api/v1/keys/{id} — subscriptum.
Reditus {"data": {…}} cum obiecto clave, aut 404
key_not_found si nemo clavis tuae illud numerum habet.
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);
Clavem mutare
PATCH https://nymbot.ai/api/v1/keys/{id} — subscriptum.
Mitte aliquid ex name, limit_sats, reset_period et
expire_at, eodem regulis sicut clavem faciendo. null sine limite, sine reformatio, sine expiratione. Mutatio periodi refractionis novum periodum a zero incipit.
Clavis revocata mutari non potest (400 key_revoked). Redde
{"data": {…}} cum obiecto clavis renovato.
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);
Clavem revocare
DELETE https://nymbot.ai/api/v1/keys/{id} — subscriptum.
Clavet iam statim, in perpetuum. In indice manet cum revoked_at positum, et videri
potest cum include_revoked=trueClavem iam revocatam revocare eodem modo respondet. Solum quinquaginta novissima claves revocatae servantur; vetustiora deleuntur cum altera clavis revocetur.
Responsio
{ "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 automaticus repletus
Porticulum Lightning cum Nostr Wallet Connect iunge, et Nymbot numerum ipse implet cum sumptus API eum minuant. Tabula API applicationis eadem configuratione habet; haec sunt puncta terminantia quae eam regunt. Omnia eorum opus est petitio signata.
Quomodo operatur: postquam postulatum API ex saldo quod vigilare elegisti debitum est, si hoc saldo sub limitem tuum cecidit, Nymbot rationem reddendam pro quantitate muneris addendi facit, portulam tuam ut id solvat rogat, et creditum addit. Quinquaginta minutis timor maxime semel pro quoque nym et saldo munus addit, ut impetu postulationum portula exhauriari non possit. In applicationibus expensio hoc non incitat. Tempus et magnitudinem ultimi muneris addendi, et ultimam errorem, in numeris inveniri; si solutio post errorem peracta est, rationem eius per... status creditionis hoc credit.
Series connectionis quemcumque eum qui eam tenet tibi permittit ut portulum tuum solvat. Nymbot
eam encryptam servat et tantum ad suas ipsas sumptus facturas solvendas utitur, sed
fac nexum tantum ad hoc, cum pecunia limitata in portulo tuo, ut maximum quod
ever solvat sit numerus quem elegisti. Portulum hoc sustinere debet pay_invoice.
Marsupium coniungere
POST https://nymbot.ai/api/v1/nwc-auto-topup/connect — subscriptum.
| Campus | Typus | Necessarium | Descriptio |
|---|---|---|---|
nwc_url | filum | Ita | Series connectionis, incipiens nostr+walletconnect://. Nymbot portulum petit pro get_info antequam id servet, et id encryptum conservat. |
threshold_sats | integer | Ita | Imple cum saldus infra hoc numero satorum descendit. Saltem 1,000. |
topup_sats | integer | Ita | Quantum addere oportet singulis vicibus. 1,000 ad 1,000,000 sats. |
tier | filum | Non | pro (defaultum) an standard: saldo spectandi et implegendi. |
Responsio
{
"data": {
"connected": true,
"threshold_sats": 5000,
"topup_sats": 20000,
"tier": "pro",
"last_topup_at": null,
"last_topup_sats": null,
"last_error": null
}
}
| Status | Quando |
|---|---|
400 | Non est catena connectionis (invalid_nwc_url); portulus per suum relay non respondit (nwc_unreachable) an examinatio recusavit (nwc_rejected); connexio libellos pecuniarios solvere non potest (nwc_missing_permission); vel summa extra limites. |
501 | Incredibilia supplementa ad hoc servum non sunt activata (nwc_unavailable). Id idem ad alia duo puncta terminalia spectat. |
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());
Configurationes legens
GET https://nymbot.ai/api/v1/nwc-auto-topup — subscriptum.
Eodem obiecto redit cum nectit, cum connected: false et cetera officia
null cum nullum malum (wallet) iunctum sit. Ipsa series connectionis numquam
reditur.
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());
Disconnectens
DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection — subscriptum.
Delet nectere stringem conservatum. Nulla amplificatio iam facitur. Ut certe sis, nectere etiam in portulente tuo revocare potes.
Responsio
{ "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());
Solvendum per petitionem sine clave
Termini pretii fixi per Lightning pro unaque postulatione tempore solvi possunt, sine clave,
sine ratione et sine saldo: POST /images/generations, POST /images/edits,
POST /videos, POST /audio/speech, POST /audio/transcriptions,
POST /audio/translations et POST /embeddingsColloquia, responsiones, et nuntii semper clavem requirunt. Petitio quae clavem portat sicut consuetum est ex saldo computatur; processus solutionis tantum incipit cum nulla clavis mittaatur.
Nymbot duas eadem sententiam dicere, ex uno backend: Lightning Labs'
L402 (etiam sub nomine veteri accipitur, LSAT) et propositum IETF
Solutio Ratio authenticationis HTTP cum lightning ratio et
charge Propositum. Utere eo quod cliens tuus intellegit.
Solutio sine clave tantum fit cum... API_L402_SECRET continet saltem 32 bytes fortuito, ut hex (64 characteres) vel base64 (44). Fac unum cum openssl rand -hex 32.
Valor brevior vel praedicibilis hoc munus desactivat et cur id fiat nuntiat. Ut eum vertas, antiquum
valorem move ad API_L402_SECRET_PREVIOUS pro die: credentia, URL status et
difficultates sub eo factae operari continuent donec expirant.
Certamen
Mitte petitionem sine Authorization caput. Si validum est, nihil currit, et
obtienes 402 Payment Required cum factura pro eo exacto quod illa postulatio constat: eadem pretio quod clavis solveret, conversum decem sats pro credito ordinario vel centum sats pro credito Pro, et ad satum integrum elevatum (saltem unum sat, et minimum creditum 0.05). Responsum tria fert. WWW-Authenticate difficultates pro eadem factura:
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 }
}
Solutio request parameter est base64url JSON:
{"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.
Certamen ad finem, ad... obligatum est Content-Type (genus mediae et, pro
multipartibus, finis eius) et ad SHA-256 eorumque corporum byte exactorum quae misisti, et per XV
minuta durat. Post solvendum, mitte similis iterum peto: idem
Content-Type et eodem JSON byte, vel pro punctis terminis multipartibus
(/images/edits, /audio/transcriptions, /audio/translations)
eadem corpus multipartium eademque limite. Maximae bibliothecae HTTP novum finem (boundary) eligunt
cumque formam codificant, ergo semel codifica et illos bytes bis mitte.
Omnis inscriptio potest petere trentes provocationes per minutam (inscriptio IPv6 ut tota /64 numeratur). Rogationes quorum inscriptio ignota est decem per minutam, quae severior est, communem habent, et est limitatio generalis in provocationibus quas Nymbot omnibus inscriptionibus mittit; rogatio quae repulsa est antequam provocatio fiat (exempli gratia cum corpore quod non est JSON validum) ad id non numeratur. Ultra hoc responsum est 429 cum Retry-After, antequam corpus legatur mittitur. Termini finitos sine clavi vel notae appellatae etiam in numerum generalem centum viginti
postulati per minutam per unum locum sine auctoritate computantur. Notam antequam corpus
legatur probat, et postulatum cuius Content-Type non est application/json (vel
multipart/form-data pro uploadis) cum recusatur 415 et numquam recipit
rationem.
Infixiones pretio aestimationis numerorum in introductio estimati, cum margine 1.5×, quoniam numerus verus postea tantum cognoscitur. Pro numeris re vera usatis numeras solvis, et pars incommutata solutionis redit ut signum reditionis.
Solutio mittitur
Solve expeditionem cum quacumque portulā Lightning. Portula tibi praeimaginem dat, sexaginta quattuor characteres hexadecimales. Deinde eundem petitionem mitte cum uno horum:
| Consilium | Caput |
|---|---|
| L402 | Authorization: L402 <macaroon>:<preimage> (LSAT etiam operatur) |
| Solutio | Authorization: Payment <base64url JSON>, ubi JSON est {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}} |
Petitio soluta responsum exacte sicut illa quae clave facta est praebet, nisiquam... nymbot
Objectum campos aequilibrii non habet: {"payment": "l402", "tier": "pro", "paid_sats": 237,
"charged_sats": 237}, et non est X-Nymbot-Balance-Sats caput. A
petitio cum Ratione Solutionis soluta etiam habet Payment-Receipt caput (base64url
JSON cum numero identificationis provocationis, cum hash solutionis ut reference, status et
timestamp). Rogationes solutae ad ullum nomen non nexa sunt, ita ut in historia quaestionum non appareant.
| Status | Quando |
|---|---|
402 payment_already_used | Omnis solutio pro uno postulatione solvit. Responsum est novum provocatio pro hac postulatione, ergo emptor qui novissimam auctoritatem servat (ut lnget simpliciter denuo solvit. |
402 payment_mismatch | Notitia ad aliud finem emissa est, Content-Type aut corpus, aut minus quam hoc postulatum nunc constat. Novum provocatio hoc postulatum cum eo venit; si solutio nimis parva erat, quod solvis revertitur ut signum reditionis (refund_token et refund_sats in corpore). |
402 payment_expired | Plus quam XV minuta ab provocatione praeterita. Nova provocatio cum eo venit. Si praeimago monstrat te pendisse, id quod pendisti redit ut signum reditionis (refund_token et refund_sats in corpore), semel; titulus tunc consumptus est. |
401 invalid_preimage | Praeimago ad summationem solutionis facturae non convertitur. Sol |
401 invalid_payment_credential | Praepostitium male formatum est, mutatum est postquam Nymbot id emisit, vel numerum solutionis nominat cuius Nymbot numquam rationem emisit. Macaroon cum condicione quam Nymbot non novit, vel cum condicionibus conflictibus, recusatur. |
429 rate_limit_exceeded | Ultra triginta signa vel claves quae vericanda non potuerunt ex hac addressio intra minutam orta sunt, aut unum signum restitutio intra minutam plus quam sexaginta vicibus missum est. Expecta 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"));
Clientes in structi mppx Per methodum Lightning provocationem solutionis ipsi superent; ad finem dirige eos et solvere sin.
Videa
Solutus POST /videos responsa 202 ut unus clavatus, etcum
status_url: GET sine ulla clave ut opus sequatur. Signatum est
et viget per XXIV horas, dum opus servatur.
{
"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..."
}
}
Serva refund_token ex hoc responso: solum hic ostenditur. Inane est dum
video formatur (GET /api/v1/l402/refunds responsa "status": "pending");
si deductio sine numeris facta deficit, solutio ei incidit. Status URL ostendit
refund_sats pro opere restituto sed numquam sigillo, itaque status URL non restitutionem communicat. Sigillum quoque examinare operem deficiente qui nemo investigavit componit.
Redributiones
Si postulatio soluta deficit et praebitor Nymbotem propter conatum monetavit, solutio retinetur et error hoc indicat, cum charged_sats, plane sicut pro rogatu signato. Si deficit
sine pecunia exigenda, error errorem fert signum reditionis pretium quod solvi:
{
"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"
}
}
Partes inutiles eodem modo revertuntur: si duas imagines petiveris et una sine pecunia debita defecerit,
responsum successus nymbot res obiectum momentum redimensionis pro eo quod deest ferit;
transcriptio cuius longitudo antea legi non potuit pretium pro maxima longitudini quam
fieri potest (nunquam plus quam triginta minuta) habet, et differentia ad veram longitudinem ut
momentum redimensionis redit; si maior quam triginta minuta evaderit, cum hoc recusatur 413
et totum solutio redit. Embeddings reddeunt quod aestimatio retinebat. Video deficiente redditur ei signo quod submissio eius reddidit.
Signum reditus est codex aleatorius 256-bit. Nymbot tantum eius hash conservat, et post 30 dies expiravit. Saldo sat continet, et potes:
- Eisce cum eo. Mitte
Authorization: Bearer REFUND-…in quibuscumque punctorum supra dictorum (OpenAI SDK id ut clavis API accipit). Pretium ex token deductum est et quod reliquum manet in eo (refund_token_satsinnymbotobjectum). Signum pretio minoris postulati respondet402refund_insufficient; defectus non computatus satoshis in eundem token revertit. - Examina id.
GET /api/v1/l402/refundseadem capite redit{"sats": 237, "status": "open", "expires_at": "..."}. - Unum signum intra minutum septuaginta vicibus saltem adhiberi potest.
- Ad nomen anonymum move. Inscribe id in Donum redime in
app Nymbot, aut chiama
POST /api/v1/l402/refunds/redeemcum petitio signata et{"refund_token": "REFUND-...", "balance": "standard"}(vel"pro"). Omnes credita ad saldo pertinunt (10 sats unumque in standard, 100 in Pro); sats quae integrum creditum non faciunt in signo remanent pro requistibus 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"
Responsio
{ "data": { "credited": 23, "tier": "standard", "balance_credits": 123, "remaining_sats": 7 } }