База знань розробників
Баланс, топ-уп і ключі
Перевірте, що у вас є, перегляньте 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 Ключ не потрібен.
Top-up - від 10 до 1 000 000 sats; Pro-top-up повинен придбати принаймні один Pro-кредит, тому він починається з 100 sats. bulk_bonus перераховує додатковий кредит на великі топ-уп, той же, що і в додатку: 10%, 15% або 20% більше на стандартні топ-уп від 500, 1000 або 5000 sats, і на Pro топ-уп від 5000, 10000 або 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);
Піднятися над блискавкою
Створює рахунок Lightning, який додає кредит до нім, до якого належить ключ. оплатити його з будь-якого гаманця Lightning, потім Перевірте його Для отримання додаткового кредиту.
POST https://nymbot.ai/api/v1/topup/create/btc-lightning Для цього потрібен ключ API.
| Поле | Тип | Необхідні | Опис |
|---|---|---|---|
amount | Номер | так | Скільки, в currencyЦе ціле число для ставки. |
currency | Стринг | Ні | SATS (відповідно до вищезазначеного порядку) USD або BTCДолари конвертуються за поточною ціною Bitcoin. |
tier | Стринг | Ні | pro (відповідно до положень) або standard• до якого балансу йде кредит. |
Стандартний кредит - 10 sats і Pro кредит - 100 sats, плюс будь-який бонус;
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 Wallet (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);
Перевірка Top-Up
Запитує, чи був сплачений рахунок і, як тільки він є, додає кредит. Перевірка є те, що кредитує його, так що після оплати, перевірка, поки стан не 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 | Створення integer (query) | Ні | За замовчуванням 1, максимум 1000; сторінка вище 400 invalid_value. |
page_count | Створення integer (query) | Ні | Ранки на сторінку. За замовчуванням 20, максимум 100. |
start_dateend_date | Стрічка (англ. string) для запиту | Ні | ISO 8601 дати та часи. |
model | Стрічка (англ. string) для запиту | Ні | Тільки ця модель. |
type | Стрічка (англ. string) для запиту | Ні | chat, responses, messages, image, video, speech, transcription або embedding. |
all_keys | Боуліанська (query) | Ні | З одним ключем: true включає кожен ключ з однієї і тієї ж нім. false. |
key_id | Стрічка (англ. string) для запиту | Ні | з підписанням заявки або з 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 Header з словом 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 Кб, а тіло потребує
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 На максі, 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 додатка у верхній частині: ваш публічний ключ, обидва баланси, скільки ключів активні (не скасовані або не закінчені), а також Автоматичний Top-Up налаштування, або
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) | Ні | Включає скасовані ключі. Default 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 | Інтеграція | Ні | Розрахунок витрат у сумі, принаймні 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 якщо жоден з ключів не має цього ID.
cURL
URL=https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"
Python
import requests
url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856"
print(requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json()["data"])
JavaScript
const url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856";
console.log((await (await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } })).json()).data);
Зміна ключа
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 додатка має ті ж налаштування; це кінцеві точки за ним. Підписана заявка.
Як це працює: після того, як запит API стягується до балансу, який ви вирішили спостерігати, якщо цей баланс впав нижче вашого порогу, Nymbot робить рахунок-фактуру за вашу суму, просить ваш гаманець сплатити його, і додає кредит. Він піднімається не більше одного разу кожні 5 хвилин для кожного німа і балансу, так що спалах запитів не може вичерпати гаманець. Витрати в додатках не викликають його. Час і розмір останнього навантаження, а також остання помилка, знаходяться в налаштуваннях; якщо платіж пройшов після помилки, перевірте його рахунок-фактуру Статус Top-Up Кредити на це.
Nymbot зберігає його зашифрованим і тільки коли-небудь використовує його для оплати власних рахунків, але зробити підключення тільки для цього, з бюджетом витрат у вашому гаманці, так що найбільше він коли-небудь може заплатити це номер вибрав вас. гаманець має підтримувати pay_invoice.
Підключення гаманця
POST https://nymbot.ai/api/v1/nwc-auto-topup/connect І підписав
| Поле | Тип | Необхідні | Опис |
|---|---|---|---|
nwc_url | Стринг | так | Зв'язок, починаючи з nostr+walletconnect://Nymbot запитує гаманець для get_info Перед тим, як його зберегти, і зберігає його зашифровано. |
threshold_sats | Інтеграція | так | Піднятися, коли баланс падає нижче за ці багато sats. |
topup_sats | Інтеграція | так | Скільки потрібно додавати кожен раз. від 1000 до 1000 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 виступає з двома версіями однієї і тієї ж ідеї – 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 шестизначних символів. Потім надіслати той же запит з одним з цих:
| схеми | Header |
|---|---|
| Л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 з ідентифікатором виклику, платіжний хеш як 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 з методом блискавки справляються з викликом оплати самі; вкажіть їх на кінцеву точку і дозвольте їм заплатити.
Відео
Оплачується 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Невдача, яка не обчислюється, повертає ставку на той же токен. - Перевірте це
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 } }