База знания Разработчиците
Баланс, върхове и ключове
Проверете какво имате, надхвърлете Lightning, надхвърлете автоматично от собствения си портфейл, вижте колко струва всяко искане и управлявайте ключовете от кода.
Тази страница е машинно преведена за удобство. Английският оригинал е версията, която се прилага.
Проверка на баланса
И вашите баланси, и колко от капака на този ключ се използва.
GET https://nymbot.ai/api/v1/credits/balance Нуждаете се от API ключ. POST Това важи и за клиентите, които го очакват.
balance е двата баланса заедно в долари на текущата цена на Bitcoin, за инструменти, които очакват едно число (null Останалото е в кредити и ставки, което е начинът, по който балансите всъщност се държат. key Описва ключа, който е поискал.Ключ, който е достигнал своя капак, все още може да провери баланса.
Отговор
{
"balance": 49.18,
"balance_sats": 42037,
"standard": { "credits": 120.4, "sats": 1204 },
"pro": { "credits": 408.33, "sats": 40833 },
"key": {
"id": "4f0c9a1be27d3856",
"name": "laptop scripts",
"limit_sats": 20000,
"period_used_sats": 3412,
"total_used_sats": 18230,
"reset_period": "monthly",
"reset_at": "2026-10-01T00:00:00Z"
}
}
| статут | Кога |
|---|---|
401 | Ключът е липсващ, неизвестен, оттеглен или изтекъл. |
cURL
curl https://nymbot.ai/api/v1/credits/balance \
-H "Authorization: Bearer $NYMBOT_API_KEY"
Python
import os
import requests
res = requests.get(
"https://nymbot.ai/api/v1/credits/balance",
headers={"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]},
)
balance = res.json()
print(balance["standard"]["sats"], balance["pro"]["sats"])
JavaScript
const res = await fetch("https://nymbot.ai/api/v1/credits/balance", {
headers: { "Authorization": "Bearer " + process.env.NYMBOT_API_KEY },
});
const balance = await res.json();
console.log(balance.standard.sats, balance.pro.sats);
Начини на плащане
Как можете да надхвърлите, и границите. мълния е единственият метод.
GET https://nymbot.ai/api/v1/topup/payment-methods Няма нужда от ключ.
Топ-уп е от 10 до 1 000 000 sats; Pro-top-up трябва да купи най-малко един Pro кредит, така че започва от 100 sats. bulk_bonus изброява допълнителния кредит за по-големите топ-уп, същият като в приложението: 10%, 15% или 20% повече за стандартните топ-уп от 500, 1000 или 5000 sats, и за Pro топ-уп от 5,000, 10,000 или 50,000 sats.
Отговор
{
"supported_methods": [
{
"method": "btc-lightning",
"display_name": "Bitcoin Lightning",
"supported_currencies": ["SATS", "USD", "BTC"],
"limits": {
"SATS": { "min": 10, "max": 1000000 },
"USD": { "min": 0.02, "max": 1170 },
"BTC": { "min": 1e-7, "max": 0.01 }
},
"tiers": ["standard", "pro"],
"default_tier": "pro",
"tier_min_sats": { "standard": 10, "pro": 100 },
"sats_per_credit": { "standard": 10, "pro": 100 },
"bulk_bonus": [
{ "bonus": 0.1, "standard_sats": 500, "pro_sats": 5000 },
{ "bonus": 0.15, "standard_sats": 1000, "pro_sats": 10000 },
{ "bonus": 0.2, "standard_sats": 5000, "pro_sats": 50000 }
]
}
]
}
cURL
curl https://nymbot.ai/api/v1/topup/payment-methods
Python
import requests
methods = requests.get("https://nymbot.ai/api/v1/topup/payment-methods").json()
print(methods["supported_methods"][0]["limits"])
JavaScript
const methods = await (await fetch("https://nymbot.ai/api/v1/topup/payment-methods")).json();
console.log(methods.supported_methods[0].limits);
Нагоре над светкавицата
Създава сметка за светкавицата, която добавя кредит към ключа, към който принадлежи ключът. Проверете го Добавяне на кредита.
POST https://nymbot.ai/api/v1/topup/create/btc-lightning Нуждаете се от API ключ.
| полето | Тип | Необходими | Описание на |
|---|---|---|---|
amount | брой | да | Колко пъти, в currencyЦяло число за залог. |
currency | Стрийт | не | SATS (В случай на неизпълнение на задължението), USD или BTCДоларите се конвертират на текущата цена на Bitcoin. |
tier | Стрийт | не | pro (в случай на неизпълнение) или standardВ кой баланс се намира кредитът. |
Стандартният кредит е 10 стотинки и Pro кредит 100 стотинки, плюс всякакъв бонус;
credits Кажи ми какво ще добави тази статия.
Отговор
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"payment_request": "lnbc100u1p5...",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": "2026-09-30T09:27:00Z",
"status": "pending"
}
| статут | Кога |
|---|---|
400 | Друг метод на пътя (unsupported_method, неизвестна валута (unsupported_currencyв) минимална стойност или минимална стойност или минимална стойност (amount_too_small, над 1 000 000 стотинки (amount_too_large) или отхвърлени от портфейла на Lightning (amount_out_of_range). |
429 | Повече от 60 фактури за този нюм, или 120 от този адрес, в един час (rate_limit_exceeded, с Retry-After). |
502 | В момента не може да се направи фактура (invoice_unavailable, с Retry-After). |
cURL
curl https://nymbot.ai/api/v1/topup/create/btc-lightning \
-H "Authorization: Bearer $NYMBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 10000, "currency": "SATS", "tier": "pro"}'
Python
import os
import requests
res = requests.post(
"https://nymbot.ai/api/v1/topup/create/btc-lightning",
headers={"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]},
json={"amount": 10000, "currency": "SATS", "tier": "pro"},
)
invoice = res.json()
print(invoice["payment_request"])
JavaScript
const res = await fetch("https://nymbot.ai/api/v1/topup/create/btc-lightning", {
method: "POST",
headers: {
"Authorization": "Bearer " + process.env.NYMBOT_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ amount: 10000, currency: "SATS", tier: "pro" }),
});
const invoice = await res.json();
console.log(invoice.payment_request);
Проверка на върха
Пита дали фактурата е платена и, след като има, добавя кредита. Проверка е това, което го кредитира, така че след плащане, проверете, докато състоянието е creditedПроверката отново след това е безопасна: кредитът се приземява веднъж, независимо колко пъти питате.
GET https://nymbot.ai/api/v1/topup/status/{invoice_id} — се нуждае от ключ от ним, който е направил фактурата.
status е pending (все още не е платен) paid (платено, но все още не е кредитирано; проверете отново), credited (на вашия баланс) или expired (не се плаща навреме). Полетата на баланса са за нивото, на което се изчислява фактурата.
Отговор
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"status": "credited",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": null,
"balance_credits": 523.33,
"balance_sats": 52333
}
| статут | Кога |
|---|---|
400 | Идентификаторът не е 64-цифровият идентификатор от повикването за създаване. |
404 | Нито един от тях не може да се похвали с това име (вж.invoice_not_found). |
cURL
curl https://nymbot.ai/api/v1/topup/status/$INVOICE_ID \
-H "Authorization: Bearer $NYMBOT_API_KEY"
Python
import os, time
import requests
headers = {"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]}
url = "https://nymbot.ai/api/v1/topup/status/" + invoice["invoice_id"]
while True:
status = requests.get(url, headers=headers).json()["status"]
if status in ("credited", "expired"):
break
time.sleep(3)
print(status)
JavaScript
const headers = { "Authorization": "Bearer " + process.env.NYMBOT_API_KEY };
const url = "https://nymbot.ai/api/v1/topup/status/" + invoice.invoice_id;
let status;
do {
await new Promise((r) => setTimeout(r, 3000));
status = (await (await fetch(url, { headers })).json()).status;
} while (status !== "credited" && status !== "expired");
console.log(status);
Искам история
Един ред на заявка: какво е било, какъв модел, колко токени и колко струва. Не се съхраняват обаждания или отговори, така че никой не се връща. Редове се съхраняват в продължение на 90 дни, най-новото първо. Ключ, който е достигнал своя таван, все още може да прочете своята история.
GET https://nymbot.ai/api/v1/queries/history — се нуждае от API ключ, който вижда собствените си искания, или Подписано искане от твоята нима, която вижда всеки ключ.
| полето | Тип | Необходими | Описание на |
|---|---|---|---|
page | Съвпадение за: Query | не | По подразбиране 1, най-много 1000; по-висока страница е 400 invalid_value. |
page_count | Съвпадение за: Query | не | Редове на страница. По подразбиране 20, най-много 100. |
start_dateend_date | Стрийт (поискане на търсене) | не | ISO 8601 дати или часове. |
model | Стрийт (поискане на търсене) | не | Само този модел. |
type | Стрийт (поискане на търсене) | не | chat, responses, messages, image, video, speech, transcription или embedding. |
all_keys | Боулиан (на английски език) Query | не | С един ключ: true включва всеки ключ от един и същ нюм. false. |
key_id | Стрийт (поискане на търсене) | не | с подписано искане, или с all_keys=trueСамо този ключ. |
Отговор
{
"data": [
{
"id": "q_71c4e9a0",
"timestamp": "2026-09-30T08:12:00Z",
"model": "anthropic/claude-sonnet-5",
"type": "chat",
"input_tokens": 1240,
"output_tokens": 380,
"cached_tokens": 0,
"cost_sats": 16.2,
"cost_usd": 0.01895,
"balance": "pro",
"key_id": "4f0c9a1be27d3856",
"web_search": false,
"status": "ok"
}
],
"pagination": { "page": 1, "page_count": 20, "total": 311, "total_pages": 16 }
}
cURL
curl "https://nymbot.ai/api/v1/queries/history?page_count=50&type=chat" \
-H "Authorization: Bearer $NYMBOT_API_KEY"
Python
import os
import requests
res = requests.get(
"https://nymbot.ai/api/v1/queries/history",
headers={"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]},
params={"page_count": 50, "type": "chat"},
)
for row in res.json()["data"]:
print(row["timestamp"], row["model"], row["cost_sats"])
JavaScript
const res = await fetch("https://nymbot.ai/api/v1/queries/history?page_count=50&type=chat", {
headers: { "Authorization": "Bearer " + process.env.NYMBOT_API_KEY },
});
for (const row of (await res.json()).data) console.log(row.timestamp, row.model, row.cost_sats);
Подписване на заявки за сметка
Създаването, промяната и оттеглянето на ключове, резюмето на сметката и автоматичните надстройки не вземат API ключ. Те вземат подпис от вашия нюм, така че изтеклият ключ може да изразходва до своя капак, но никога не може да направи друг ключ или да повиши собствения си капак.
Приложението прави това за вас: всичко в него Огънят Този раздел ви е необходим само за да управлявате ключовете от собствения си код.
Подписът е събитие Nostr от типа 27235 (NIP-98), изпратено base64-кодирано в
Authorization Хедър с думата Nostr На преден план:
Събитието
{
"kind": 27235,
"created_at": 1790726400,
"tags": [
["u", "https://nymbot.ai/api/v1/keys"],
["method", "POST"],
["nonce", "9c4e21f07a3b...16 random bytes in hex"],
["payload", "3f1a0d7c8e2b...sha256 of the exact request body in hex"]
],
"content": "",
"pubkey": "your public key in hex",
"id": "...",
"sig": "..."
}
uе пълен URL адрес на заявката, включващ низ от заявки, точно както е изпратен.methodТова е HTTP методът.payloadе SHA-256 на тялото на суровото искане, в хекса.POSTиPATCH, и тялото, което изпращате, трябва да бъде байт за байт този, който хаширате.created_atтрябва да е в рамките на 60 секунди от часа на сървъра.- Всяко събитие работи веднъж, а
GETвключени, така че заснетата заглавие не може да бъде възпроизведена отново. Подпишете нова за всяка заявка.nonceетикет с случайна стойност, така че две заявки, подписани в една и съща секунда, все още се различават. - Тялото на подписано искане може да бъде най-много 64 KB, а тялото се нуждае от
Content-Type: application/json.
Изчезнало събитие се завръща 401 missing_nostr_auth; един, който е лошо оформен, лошо подписан, твърде стар, или за различен URL, метод или тяло връща
invalid_nostr_auth, с причината в съобщението; един повторно използван се връща
nostr_auth_replayedПодписът се проверява преди тялото да бъде прочетено и всеки адрес може да се провали 30 пъти в минута (IPv6 адресът се брои като цяло /64); след това получава 429 с
Retry-After.
Браузърите могат да извикват тези крайни точки само от собствените сайтове на Nymbot (https://nymbot.ai,
https://nymchat.app Страница на всеки друг сайт не получава CORS заглавия обратно, така че не може да чете това, което те връщат.
OriginТе не са засегнати.
Подписването се нуждае от тайния ключ на вашия ним (на nsec), който контролира всичко: вашата самоличност, историята и баланса ви. Само го поставете в скрипт на машина, на която се доверявате, прочетете го от околната среда, вместо да го напишете в файла, и предпочитате приложението, когато можете.
Тези помощници изграждат заглавието. По-късните примери на тази страница ги използват. Те четат тайния ключ в хекса от NOSTR_SECRET_HEX; cURL един използва
НОК инструмент за командния ред, който взема nsec или хекс ключ, и sha256sum за MacOS, shasum -a 256).
cURL
nostr_auth() {
method="$1"; url="$2"; body="$3"
nonce=$(openssl rand -hex 16)
if [ -n "$body" ]; then
hash=$(printf '%s' "$body" | sha256sum | cut -d' ' -f1)
event=$(nak event --sec "$NOSTR_SECRET_HEX" -k 27235 -t "u=$url" -t "method=$method" -t "nonce=$nonce" -t "payload=$hash")
else
event=$(nak event --sec "$NOSTR_SECRET_HEX" -k 27235 -t "u=$url" -t "method=$method" -t "nonce=$nonce")
fi
printf 'Nostr %s' "$(printf '%s' "$event" | base64 | tr -d '\n')"
}
Python
# pip install coincurve requests
import base64, hashlib, json, os, time
from coincurve import PrivateKey, PublicKeyXOnly
SECRET = bytes.fromhex(os.environ["NOSTR_SECRET_HEX"])
def nostr_auth(method, url, body=b""):
pubkey = PublicKeyXOnly.from_secret(SECRET).format().hex()
tags = [["u", url], ["method", method], ["nonce", os.urandom(16).hex()]]
if body:
tags.append(["payload", hashlib.sha256(body).hexdigest()])
created_at = int(time.time())
serialized = json.dumps([0, pubkey, created_at, 27235, tags, ""], separators=(",", ":"), ensure_ascii=False)
event_id = hashlib.sha256(serialized.encode()).digest()
event = {
"id": event_id.hex(),
"pubkey": pubkey,
"created_at": created_at,
"kind": 27235,
"tags": tags,
"content": "",
"sig": PrivateKey(SECRET).sign_schnorr(event_id).hex(),
}
return "Nostr " + base64.b64encode(json.dumps(event).encode()).decode()
JavaScript
// npm install nostr-tools
import { createHash, randomBytes } from "node:crypto";
import { finalizeEvent } from "nostr-tools/pure";
const secret = Buffer.from(process.env.NOSTR_SECRET_HEX, "hex");
export function nostrAuth(method, url, body = "") {
const tags = [["u", url], ["method", method], ["nonce", randomBytes(16).toString("hex")]];
if (body) tags.push(["payload", createHash("sha256").update(body).digest("hex")]);
const event = finalizeEvent(
{ kind: 27235, created_at: Math.floor(Date.now() / 1000), tags, content: "" },
secret,
);
return "Nostr " + Buffer.from(JSON.stringify(event)).toString("base64");
}
Резюме на сметката
Какво показва API листът на приложението в горната част: вашият публичен ключ, двата баланса, колко ключа са активни (не са отменени или изтекли) и Автоматично натоварване настройки или
null когато сървърът не ги предлага.
GET https://nymbot.ai/api/v1/account Нуждае се от Подписано искане.
Отговор
{
"data": {
"pubkey": "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
"balances": {
"standard": { "credits": 120.4, "sats": 1204 },
"pro": { "credits": 408.33, "sats": 40833 }
},
"keys_active": 3,
"nwc_auto_topup": {
"connected": true, "threshold_sats": 5000, "topup_sats": 20000, "tier": "pro",
"last_topup_at": null, "last_topup_sats": null, "last_error": null
}
}
}
cURL
URL=https://nymbot.ai/api/v1/account
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"
Python
import requests
url = "https://nymbot.ai/api/v1/account"
print(requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json())
JavaScript
const url = "https://nymbot.ai/api/v1/account";
const res = await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } });
console.log(await res.json());
Управление на ключове
Крайните точки зад списъка с ключове на приложението. Всички те се нуждаят от Подписано исканеВсеки ключ се връща в следната форма, с времена в ISO 8601 и суми в sats:
Ключови обекти
{
"id": "4f0c9a1be27d3856",
"name": "laptop scripts",
"hint": "sk-nymbot-Qm7x…c2Lw",
"limit_sats": 20000,
"reset_period": "monthly",
"reset_at": "2026-10-01T00:00:00Z",
"expire_at": null,
"period_used_sats": 3412,
"total_used_sats": 18230,
"created_at": "2026-08-14T09:21:07Z",
"updated_at": "2026-09-02T17:40:55Z",
"last_used_at": "2026-09-30T08:12:00Z",
"revoked_at": null
}
hint Достатъчно е да разпознаете ключ, но не и да го използвате.Самият ключ се връща само веднъж, когато е направен.
Списък на ключовете
GET https://nymbot.ai/api/v1/keys — Аз съм подписал.
| полето | Тип | Необходими | Описание на |
|---|---|---|---|
include_revoked | Боулиан (на английски език) Query | не | Включва отменени ключове. по подразбиране false. |
Отговор
{ "data": [ { "id": "4f0c9a1be27d3856", "name": "laptop scripts", "hint": "sk-nymbot-Qm7x…c2Lw", "...": "..." } ] }
cURL
URL=https://nymbot.ai/api/v1/keys
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"
Python
import requests
url = "https://nymbot.ai/api/v1/keys"
for key in requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json()["data"]:
print(key["id"], key["name"], key["period_used_sats"], key["limit_sats"])
JavaScript
const url = "https://nymbot.ai/api/v1/keys";
const { data } = await (await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } })).json();
for (const key of data) console.log(key.id, key.name, key.period_used_sats, key.limit_sats);
Създаване на ключ
POST https://nymbot.ai/api/v1/keys Връщане - връщане 201.
| полето | Тип | Необходими | Описание на |
|---|---|---|---|
name | Стрийт | да | 1 до 40 знака, различни от останалите ви активни ключове (игнориране на случая). |
limit_sats | интегритет | не | Капацитетът на разходите в sats, най-малко 1. |
reset_period | Стрийт | не | daily, weekly или monthlyнуждите limit_satsОставете го за капачка, която никога не се възстановява. |
expire_at | string или integer | не | Когато ключът спре да работи: ISO 8601 време, или милисекунди от 1970 година. |
Отговор на въпроса (201)
{
"data": {
"id": "4f0c9a1be27d3856",
"name": "laptop scripts",
"hint": "sk-nymbot-Qm7x…c2Lw",
"limit_sats": 20000,
"reset_period": "monthly",
"key": "sk-nymbot-Qm7x...c2Lw",
"...": "the rest of the key object"
}
}
| статут | Кога |
|---|---|
400 | Липсващо или твърде дълго име; вече използвано име (duplicate_name); таван, който не е цяло число от най-малко 1; период на нулиране без таван; изтичане в миналото; неизвестно поле (unknown_parameter); или 25 активни ключове вече (too_many_keys). |
429 | Повече от 60 ключа, направени от този ним, или 120 от този адрес, в един час (rate_limit_exceeded, с Retry-After). |
cURL
URL=https://nymbot.ai/api/v1/keys
BODY='{"name":"laptop scripts","limit_sats":20000,"reset_period":"monthly"}'
curl "$URL" \
-H "Authorization: $(nostr_auth POST "$URL" "$BODY")" \
-H "Content-Type: application/json" \
-d "$BODY"
Python
import json
import requests
url = "https://nymbot.ai/api/v1/keys"
body = json.dumps({"name": "laptop scripts", "limit_sats": 20000, "reset_period": "monthly"}).encode()
res = requests.post(
url,
data=body,
headers={"Authorization": nostr_auth("POST", url, body), "Content-Type": "application/json"},
)
print(res.json()["data"]["key"])
JavaScript
const url = "https://nymbot.ai/api/v1/keys";
const body = JSON.stringify({ name: "laptop scripts", limit_sats: 20000, reset_period: "monthly" });
const res = await fetch(url, {
method: "POST",
headers: { "Authorization": nostrAuth("POST", url, body), "Content-Type": "application/json" },
body,
});
console.log((await res.json()).data.key);
Четене на ключ
GET https://nymbot.ai/api/v1/keys/{id} — Аз съм подписал.
Връщане {"data": {…}} с ключовия обект, или 404
key_not_found Ако вашият ключ няма този идентификатор.
cURL
URL=https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"
Python
import requests
url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856"
print(requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json()["data"])
JavaScript
const url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856";
console.log((await (await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } })).json()).data);
Смяна на ключ
PATCH https://nymbot.ai/api/v1/keys/{id} — Аз съм подписал.
Изпратете някой от name, limit_sats, reset_period и
expire_atсъщите правила, както при създаването на ключ. null Изчиства поле: няма капаци, няма нулиране, няма изтичане. Промяната на периода на нулиране започва нов период от нула.400 key_revoked• Връщане
{"data": {…}} с актуализирания ключов обект.
cURL
URL=https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856
BODY='{"limit_sats":50000,"expire_at":null}'
curl -X PATCH "$URL" \
-H "Authorization: $(nostr_auth PATCH "$URL" "$BODY")" \
-H "Content-Type: application/json" \
-d "$BODY"
Python
import json
import requests
url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856"
body = json.dumps({"limit_sats": 50000, "expire_at": None}).encode()
res = requests.patch(
url,
data=body,
headers={"Authorization": nostr_auth("PATCH", url, body), "Content-Type": "application/json"},
)
print(res.json()["data"])
JavaScript
const url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856";
const body = JSON.stringify({ limit_sats: 50000, expire_at: null });
const res = await fetch(url, {
method: "PATCH",
headers: { "Authorization": nostrAuth("PATCH", url, body), "Content-Type": "application/json" },
body,
});
console.log((await res.json()).data);
Отмяна на ключ
DELETE https://nymbot.ai/api/v1/keys/{id} — Аз съм подписал.
Спира ключа веднага, за добро. Той остава в списъка с revoked_at Намерени са и могат да се видят include_revoked=trueОттеглянето на ключ, който вече е оттеглен, отговаря по същия начин. Само най-новите 50 оттеглени ключа се запазват; по-старите се изтриват, когато се оттегли друг ключ.
Отговор
{ "data": { "id": "4f0c9a1be27d3856", "revoked": true } }
cURL
URL=https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856
curl -X DELETE "$URL" -H "Authorization: $(nostr_auth DELETE "$URL")"
Python
import requests
url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856"
print(requests.delete(url, headers={"Authorization": nostr_auth("DELETE", url)}).json())
JavaScript
const url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856";
const res = await fetch(url, { method: "DELETE", headers: { "Authorization": nostrAuth("DELETE", url) } });
console.log(await res.json());
Автомобилът NWC Auto-top-up
Свържете портфейла на Lightning с Nostr Wallet Connect и Nymbot ще постави баланса сам по себе си, когато разходите за API го изпълняват ниско. Подписано искане.
Как работи: След като заявката за API се таксува на баланса, който сте избрали да гледате, ако този баланс е паднал под прага ви, Nymbot издава фактура за сумата ви, пита портфейла ви да я плати и добавя кредита. Той се натрупва най-много веднъж на всеки 5 минути за всеки нюм и баланс, така че избухването на искания не може да изтегли портфейла. Изразходването в приложенията не го задейства. Времето и размерът на последната надстройка и последната грешка са в настройките; ако плащането е минало след грешка, проверете фактурата си с Статусът на върха Кредитирай го
Nymbot го съхранява шифровано и само някога го използва, за да плати собствените си фактури, но направете връзка само за това, с бюджет за разходи в портфейла си, така че най-много, което някога може да плати, е номер, който сте избрали. pay_invoice.
Свързване на портфейл
POST https://nymbot.ai/api/v1/nwc-auto-topup/connect — Аз съм подписал.
| полето | Тип | Необходими | Описание на |
|---|---|---|---|
nwc_url | Стрийт | да | Връзката, започвайки от nostr+walletconnect://Nymbot пита портфейла за get_info преди да го съхранява и го съхранява криптирано. |
threshold_sats | интегритет | да | Нагоре, когато балансът падне под тези много sats. най-малко 1000. |
topup_sats | интегритет | да | Колко да добавя всеки път. 1000 до 1 000 000 sats. |
tier | Стрийт | не | pro (в случай на неизпълнение) или standard: балансът да се наблюдава и да се издига. |
Отговор
{
"data": {
"connected": true,
"threshold_sats": 5000,
"topup_sats": 20000,
"tier": "pro",
"last_topup_at": null,
"last_topup_sats": null,
"last_error": null
}
}
| статут | Кога |
|---|---|
400 | не е свързан с връзката (invalid_nwc_url(Възможно ли е да не се отговори на въпроса за разпределението)nwc_unreachable) или се отказва от проверката (nwc_rejected); връзката не може да плати фактури (nwc_missing_permissionили сума, която е извън границите. |
501 | Автоматичните надстройки не са включени за този сървър (nwc_unavailableСъщото се отнася и за останалите две крайни точки. |
cURL
URL=https://nymbot.ai/api/v1/nwc-auto-topup/connect
BODY='{"nwc_url":"nostr+walletconnect://...","threshold_sats":5000,"topup_sats":20000,"tier":"pro"}'
curl "$URL" \
-H "Authorization: $(nostr_auth POST "$URL" "$BODY")" \
-H "Content-Type: application/json" \
-d "$BODY"
Python
import json, os
import requests
url = "https://nymbot.ai/api/v1/nwc-auto-topup/connect"
body = json.dumps({
"nwc_url": os.environ["NWC_URL"],
"threshold_sats": 5000,
"topup_sats": 20000,
"tier": "pro",
}).encode()
res = requests.post(
url,
data=body,
headers={"Authorization": nostr_auth("POST", url, body), "Content-Type": "application/json"},
)
print(res.json())
JavaScript
const url = "https://nymbot.ai/api/v1/nwc-auto-topup/connect";
const body = JSON.stringify({
nwc_url: process.env.NWC_URL,
threshold_sats: 5000,
topup_sats: 20000,
tier: "pro",
});
const res = await fetch(url, {
method: "POST",
headers: { "Authorization": nostrAuth("POST", url, body), "Content-Type": "application/json" },
body,
});
console.log(await res.json());
Прочетете настройките
GET https://nymbot.ai/api/v1/nwc-auto-topup — Аз съм подписал.
Връща същия обект като свързване, с connected: false и други полета
null когато няма свързан портфейл. самата връзка никога не се връща.
cURL
URL=https://nymbot.ai/api/v1/nwc-auto-topup
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"
Python
import requests
url = "https://nymbot.ai/api/v1/nwc-auto-topup"
print(requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json())
JavaScript
const url = "https://nymbot.ai/api/v1/nwc-auto-topup";
console.log(await (await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } })).json());
Откъсване
DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection — Аз съм подписал.
Изтрива съхранената връзка. Не се правят повече надстройки. За да сте сигурни, можете също да оттеглите връзката в портфейла си.
Отговор
{ "data": { "connected": false, "threshold_sats": null, "topup_sats": null, "tier": null, "last_topup_at": null, "last_topup_sats": null, "last_error": null } }
cURL
URL=https://nymbot.ai/api/v1/nwc-auto-topup/connection
curl -X DELETE "$URL" -H "Authorization: $(nostr_auth DELETE "$URL")"
Python
import requests
url = "https://nymbot.ai/api/v1/nwc-auto-topup/connection"
print(requests.delete(url, headers={"Authorization": nostr_auth("DELETE", url)}).json())
JavaScript
const url = "https://nymbot.ai/api/v1/nwc-auto-topup/connection";
const res = await fetch(url, { method: "DELETE", headers: { "Authorization": nostrAuth("DELETE", url) } });
console.log(await res.json());
Плащане по заявка без ключ
Крайните точки с фиксирана цена могат да бъдат платени за едно искане наведнъж през Lightning, без ключ, без сметка и без баланс: POST /images/generations, POST /images/edits,
POST /videos, POST /audio/speech, POST /audio/transcriptions,
POST /audio/translations и POST /embeddingsЧат, отговори и съобщения винаги се нуждаят от ключ. Заявка, която носи ключ, се начислява към баланса както обикновено; потокът от плащания започва само когато няма ключ.
Nymbot говори две версии на една и съща идея, от един backend: Lightning Labs
Е402 (също приети под старото си име, LSAT) и проекта на IETF
Плащането Схема за HTTP аутентификация с lightning Метод и
charge Използвайте това, което клиентът ви разбира.
Плащането без ключ е само когато API_L402_SECRET съдържа най-малко 32 случайни байта, като шестоъгълник (64 знака) или base64 (44). openssl rand -hex 32По-кратка или предположима стойност изключва функцията и регистрира защо.За да я завъртите, преместете старата стойност на API_L402_SECRET_PREVIOUS за един ден: поверителностите, URL адресите на състоянието и предизвикателствата, направени по него, продължават да работят, докато изтекат.
Предизвикателството
Изпратете заявката с не Authorization ако е валидна, нищо не работи и получавате 402 Payment Required с фактура за точно това, което искането струва: същата цена, която ключът би платил, конвертиран на 10 sats стандартен кредит или 100 sats Pro кредит и закръглено до цял sat (най-малко 1 sat, и най-малко 0.05 кредитен минимум). WWW-Authenticate Предизвикателства за една и съща сметка:
HTTP/1.1 402 Payment Required
Content-Type: application/problem+json; charset=utf-8
Cache-Control: no-store
WWW-Authenticate: L402 macaroon="AgJC...", invoice="lnbc2370n1..."
WWW-Authenticate: LSAT macaroon="AgJC...", invoice="lnbc2370n1..."
WWW-Authenticate: Payment id="kM9x...", realm="nymbot", method="lightning", intent="charge",
request="eyJhbW91bnQiOiIyMzciLC...", description="Nymbot API POST /images/generations (237 sats)",
digest="sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:", expires="2026-09-30T12:15:00.000Z",
opaque="eyJlbmRwb2ludCI6IlBPU1QgL2ltYWdlcy9nZW5lcmF0aW9ucyJ9"
{
"type": "https://paymentauth.org/problems/payment-required",
"title": "Payment Required",
"status": 402,
"detail": "This request costs 237 sats. Pay the Lightning invoice, then send the identical request again ...",
"challengeId": "kM9x...",
"amount_sats": 237,
"invoice": "lnbc2370n1...",
"payment_hash": "9db1370f...",
"expires_at": "2026-09-30T12:15:00.000Z",
"error": { "message": "This request costs 237 sats. ...", "type": "payment_required", "code": "payment_required", "param": null }
}
Плащането request Параметърът е base64url JSON:
{"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.
Едно предизвикателство е свързано с крайната точка, с Content-Type (видът на медията и, за многочасти, границата му) и на SHA-256 на точните байтове на тялото, които сте изпратили, и трае 15 минути. идентични Отново искане: същото
Content-Type и същите JSON байтове, или за множество крайни точки (/images/edits, /audio/transcriptions, /audio/translationsПовечето HTTP библиотеки избират нова граница всеки път, когато кодират формуляр, така че кодирайте го веднъж и изпращайте тези байтове два пъти.
Всеки адрес може да поиска 30 предизвикателства на минута (IPv6 адрес се брои като цяло /64). Заявления, чийто адрес не е известен, споделят по-строг 10 на минута, и има обща граница за предизвикателствата Nymbot проблеми във всички адреси; искане, отхвърлено преди да бъде направено предизвикателство (например с тяло, което не е валидно JSON) не се брои към него. 429 с Retry-AfterПлатени крайни точки, които се обаждат без ключ или поверителност, също се броят към общия лимит от 120 неоторизирани искания в минута на адрес. Content-Type Не е application/json (или
multipart/form-data за изтегляне) се отхвърля с 415 Никога не получава фактура.
Вгражданията се оценяват въз основа на оценка на токените в входа, с марж от 1.5 пъти, тъй като действителният брой е известен само след това. Възстановяване на токен.
Изпращане на плащането
Платете сметката с всеки портфейл на Lightning. Портфейлът ви дава предварителното изображение, 64 шестоъгълни знака. След това изпратете същото искане с едно от тези:
| схемата | Хедър |
|---|---|
| Е402 | Authorization: L402 <macaroon>:<preimage> (LSAT работи също) |
| Плащането | Authorization: Payment <base64url JSON>Къде е JSON {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}} |
Платената заявка отговаря точно като тази, направена с ключ, с изключение на това, че nymbot
Обектът няма полета за баланс: {"payment": "l402", "tier": "pro", "paid_sats": 237,
"charged_sats": 237}И там няма X-Nymbot-Balance-Sats Заявка, платена с схемата за плащане, също получава Payment-Receipt header (base64url JSON с ID за предизвикателство, плащане хаш като reference, status и
timestampПлатените заявки не са обвързани с нима, така че те не се появяват в историята на заявките.
| статут | Кога |
|---|---|
402 payment_already_used | Всяко плащане плаща за едно искане.Отговорът е ново предизвикателство за това искане, така че клиентът, който кешира последната си поверителност (като lnget Отново просто се върна. |
402 payment_mismatch | Кредитът е издаден за друга крайна точка, Content-Type или тялото, или плаща по-малко от това искане сега струва. ново предизвикателство за това искане идва с него; ако плащането е твърде малко, това, което сте платили, се връща като Възстановяване на токен (refund_token и refund_sats в рамките на тялото). |
402 payment_expired | Повече от 15 минути са минали от предизвикателството.Ново предизвикателство идва с него.Ако предварителното изображение показва, че сте платили, това, което сте платили, се връща като Възстановяване на токен (refund_token и refund_sats в тялото), веднъж; след това се използва доверието. |
401 invalid_preimage | Предварителното изображение не хашира платежния хаш на фактурата. |
401 invalid_payment_credential | Удостоверението е дефектно, е променено, след като Nymbot го е издал, или имената на плащане хаш Nymbot никога не е издавал фактура за. |
429 rate_limit_exceeded | Повече от 30 идентификационни данни или ключове, които не успяха да се потвърдят, дойдоха от този адрес в рамките на минута, или един токен за възстановяване беше изпратен повече от 60 пъти в минута. Retry-After. |
cURL
BODY='{"model":"nano-banana","prompt":"a lighthouse at dusk","response_format":"b64_json"}'
URL=https://nymbot.ai/api/v1/images/generations
# 1. Get the challenge
CH=$(curl -s -D - -o /dev/null "$URL" -H "Content-Type: application/json" -d "$BODY" | grep -i '^www-authenticate: L402')
MAC=$(echo "$CH" | sed -E 's/.*macaroon="([^"]+)".*/\1/')
INVOICE=$(echo "$CH" | sed -E 's/.*invoice="([^"]+)".*/\1/')
# 2. Pay $INVOICE with your wallet and copy the preimage
PREIMAGE=...
# 3. Send the identical request with the credential
curl "$URL" -H "Content-Type: application/json" -H "Authorization: L402 $MAC:$PREIMAGE" -d "$BODY"
lnget
# lnget (Lightning Labs) pays L402 challenges from your own lnd node and retries for you
lnget -X POST -H "Content-Type: application/json" \
-d '{"model":"nano-banana","prompt":"a lighthouse at dusk","response_format":"b64_json"}' \
https://nymbot.ai/api/v1/images/generations
Python
import base64, json, re
import requests
url = "https://nymbot.ai/api/v1/images/generations"
body = json.dumps({"model": "nano-banana", "prompt": "a lighthouse at dusk", "response_format": "b64_json"}).encode()
headers = {"Content-Type": "application/json"}
challenge = requests.post(url, data=body, headers=headers)
assert challenge.status_code == 402
info = challenge.json()
print("Pay", info["amount_sats"], "sats:", info["invoice"])
preimage = pay_with_your_wallet(info["invoice"]) # 64 hex characters
# L402
mac = re.search(r'L402 macaroon="([^"]+)"', challenge.headers["WWW-Authenticate"]).group(1)
res = requests.post(url, data=body, headers={**headers, "Authorization": f"L402 {mac}:{preimage}"})
print(res.json()["nymbot"])
JavaScript
const url = "https://nymbot.ai/api/v1/images/generations";
const body = JSON.stringify({ model: "nano-banana", prompt: "a lighthouse at dusk", response_format: "b64_json" });
const headers = { "Content-Type": "application/json" };
const challenge = await fetch(url, { method: "POST", headers, body });
const www = challenge.headers.get("www-authenticate");
// The Payment scheme: echo every challenge parameter back with the preimage
const start = www.indexOf("Payment ");
const params = Object.fromEntries([...www.slice(start + 8).matchAll(/(\w+)="((?:[^"\\]|\\.)*)"/g)].map((m) => [m[1], m[2]]));
const { invoice } = JSON.parse(Buffer.from(params.request, "base64url").toString()).methodDetails;
const preimage = await payWithYourWallet(invoice);
const credential = Buffer.from(JSON.stringify({ challenge: params, payload: { preimage } })).toString("base64url");
const res = await fetch(url, { method: "POST", headers: { ...headers, Authorization: `Payment ${credential}` }, body });
console.log((await res.json()).nymbot, res.headers.get("payment-receipt"));
Клиентите са изградени на mppx С помощта на метода Lightning се справяте сами с предизвикателството за плащане; насочете ги към крайната точка и ги оставете да платят.
Видеото
Платени са POST /videos отговори 202 като ключова една, плюс а
status_url: GET Той е подписан и работи в продължение на 24 часа, докато работата е запазена.
{
"id": "vid_...",
"status": "in_progress",
"status_url": "https://nymbot.ai/api/v1/videos/vid_...?exp=1790000000&sig=...",
"nymbot": {
"payment": "l402", "tier": "pro", "paid_sats": 4800, "charged_sats": 4800,
"refund_token": "REFUND-5E0B..."
}
}
Дръжте го refund_token от този отговор: той се показва само тук. Той е празен, докато видеотоGET /api/v1/l402/refunds отговори "status": "pending"); ако възпроизвеждането се провали без фактуриране, плащането се приземява върху него.
refund_sats за възстановена работа, но никога токена, така че споделянето на URL адреса на състоянието не споделя възстановяването.
възстановяване
Ако платеното искане се провали и доставчикът е таксувал Nymbot за опита, плащането се запазва и грешката казва така, с charged_sats, точно както за ключово искане. Ако той се провали, без да бъде фактуриран, грешката носи Възстановяване на токен Заслужава си това, което сте платили:
{
"error": {
"message": "The image generator failed. Nothing was charged. Please try again. The 237 sats you paid are on refund token REFUND-...",
"type": "api_error",
"code": "upstream_error",
"refund_token": "REFUND-0C15DBED145D59131BA70298A413ADEB3D9B9AB082C476EA70A5BD38FCA5DE6D",
"refund_sats": 237,
"refund_expires_at": "2026-10-30T12:00:00.000Z"
}
}
Неизползваните части се връщат по същия начин: ако сте поискали две снимки и едното не е разчитано, отговорът на успеха nymbot обектът носи токен за възстановяване за липсващия; транскрипция, чиято дължина не може да бъде прочетена предварително, се цени за най-дългата, която може да бъде файла (никога не повече от 30 минути), а разликата с реалната дължина се връща като токен за възстановяване; ако се окаже, че е по-дълга от 30 минути, тя се отхвърля с 413
Вгражданията връщат това, което е задържано от оценката.Неуспешното видео връща токена, който е върнато от подаденото.
Токенът за възстановяване е случайно 256-битов код. Nymbot съхранява само своя хеш и изтича след 30 дни.
- Платете с него. Изпрати
Authorization: Bearer REFUND-…За да се отървете от този проблем, е необходимо да се избягва използването на антибиотици, като се вземат под внимание всички фактори, които причиняват възпаление (refund_token_satsВ наnymbotТокен, който струва по-малко от отговора на заявката402refund_insufficientНеизчислена грешка поставя sats обратно на същия токен. - Проверете го
GET /api/v1/l402/refundsсъс същия хедър се връща{"sats": 237, "status": "open", "expires_at": "..."}. - Един токен може да се използва най-много 60 пъти в минута.
- Преместете го в нюанс. Поставете го в Подарете си подарък в приложението Nymbot, или повикване
POST /api/v1/l402/refunds/redeemс а Подписано искане и{"refund_token": "REFUND-...", "balance": "standard"}(или"pro"Цели кредити отиват в баланса (10 sats всеки на стандарт, 100 на Pro); ставки, които не правят цял кредит остават на токена за API заявки.
cURL
URL=https://nymbot.ai/api/v1/l402/refunds/redeem
BODY='{"refund_token":"REFUND-...","balance":"standard"}'
curl "$URL" \
-H "Authorization: $(nostr_auth POST "$URL" "$BODY")" \
-H "Content-Type: application/json" \
-d "$BODY"
Отговор
{ "data": { "credited": 23, "tier": "standard", "balance_credits": 123, "remaining_sats": 7 } }