База знаний Разработчики
Баланс, верхние слои и ключи
Проверьте, что у вас есть, переверните Lightning, автоматически переверните свой собственный кошелек, посмотрите, сколько стоит каждый запрос, и управляйте ключами из кода.
Эта страница для удобства переведена автоматически. Применяется английский оригинал.
Проверить баланс
Как ваши балансы, так и то, сколько используется крышки этого ключа.
GET https://nymbot.ai/api/v1/credits/balance Нужен ключ API. POST Работает и для клиентов, которые этого ожидают.
balance это два баланса вместе в долларах по текущей цене Биткойна, для инструментов, которые ожидают единого числа (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 топ-упы от 5000, 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);
Вверх над молнией
Создает счет 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) или отклоненный молниеносным кошельком (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);
Хочется истории
Один ряд на запрос: что это было, какая модель, сколько токенов и сколько это стоило. Никаких запросов или ответов не сохраняется, поэтому никто не возвращается.
GET https://nymbot.ai/api/v1/queries/history — нужен ключ API, который видит свои запросы, или Подписанный запрос от твоего нима, который видит каждый ключ.
| Поле | Тип | Требуется | Описание |
|---|---|---|---|
page | Чистая часть (query) | Нет | По умолчанию 1, максимум 1000; более высокая страница 400 invalid_value. |
page_count | Чистая часть (query) | Нет | По умолчанию 20 строк, максимум 100. |
start_dateend_date | String (требование) | Нет | ISO 8601 Даты и времена. |
model | String (требование) | Нет | Только эта модель. |
type | String (требование) | Нет | chat, responses, messages, image, video, speech, transcription или embedding. |
all_keys | Боулиан (поиск | Нет | С одним ключом: 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. Они берут подпись от вашего nym, так что утерянный ключ может потратить до своего предела, но никогда не может сделать другой ключ или повысить свой собственный.
Приложение делает это для вас: все в своем Огонь Sheet использует эти конечные точки. Вам нужен только этот раздел для управления ключами из собственного кода.
Подпись является событием 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 Для 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 | Боулиан (поиск | Нет | Включить отменяемые ключи. по умолчанию 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 | integer | Нет | Капитал расходов в 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 минут для каждого нима и баланса, так что всплеск запросов не может вытащить кошелек. Расходы в приложениях не запускают его. Время и размер последней суммы, и последняя ошибка, находятся в настройках; если оплата прошла после ошибки, проверяйте свой счет с Статус Top-Up Кредит на это.
Нимбот хранит его зашифрованным и только когда-либо использует его для оплаты собственных счетов-фактур, но сделать подключение только для этого, с расходным бюджетом в вашем кошельке, так что больше всего он может когда-либо заплатить - это номер вы выбрали. кошелек должен поддерживать pay_invoice.
Подключение кошелька
POST https://nymbot.ai/api/v1/nwc-auto-topup/connect — Вы подписали
| Поле | Тип | Требуется | Описание |
|---|---|---|---|
nwc_url | Стринг | Да | Схема соединения, начинающаяся nostr+walletconnect://Nymbot запрашивает кошелек для get_info перед тем, как сохранить его, и хранить его зашифрованным. |
threshold_sats | integer | Да | Вверх, когда баланс падает ниже этих многочисленных ставок. |
topup_sats | integer | Да | Сколько добавлять каждый раз. от 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 символа) или база64 (44). openssl rand -hex 32Более короткое или предсказуемое значение отключает функцию и регистрирует, почему. API_L402_SECRET_PREVIOUS в течение одного дня: аккредитации, URL-адреса статуса и задачи, сделанные в соответствии с ним, продолжают работать до тех пор, пока они не истекают.
вызов
Отправить запрос с No 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 с 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 с методом молнии справляться с платежным вызовом сами; указать их на конечную точку и позволить им заплатить.
Видео
Оплачивается 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-…в любой из вышеуказанных конечных точек (OpenAI SDK принимает его в качестве ключа API). цена исходит от токена и что остается на нем (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 } }