Прескокнете до содржината
Враќање на Nymbot

База на знаење Развивачи

Баланс, врвови и клучеви

Проверете што имате, надминете Lightning, надминете автоматски од сопствениот паричник, видете што чини секое барање и управувајте со клучевите од кодот.

Проверка на балансот

И вашите баланси, и колку од капа на овој клуч се користи.

GET https://nymbot.ai/api/v1/credits/balance Потребен ви е API клуч. POST Работи и за клиентите кои го очекуваат тоа.

balance е двата салда заедно во долари на тековната цена на Bitcoin, за алатки кои очекуваат еден број (null Останатото е во кредити и sats, што е како салдо всушност се чуваат. 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 ставки; Про топ-уп мора да купи најмалку еден Про кредит, па тоа започнува со 100 ставки. bulk_bonus Листа на дополнителни кредити на поголеми врвови, исто како и во апликацијата: 10%, 15% или 20% повеќе на стандардни врвови од 500, 1.000 или 5.000 sats, и на Про врвови од 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 sats и Про кредит 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 милион долари)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);

Желбата за историја

Еден ред по барање: што беше, кој модел, колку токени и што чини. Не се чуваат повици или одговори, па никој не се враќа. Редови се чуваат за 90 дена, најновиот прв.

GET https://nymbot.ai/api/v1/queries/history потребен е API клуч, кој ги гледа сопствените барања, или Потпишано барање од вашиот ним, кој ги гледа сите клучеви.

ПолетоТипПотребниОпис на
pageцелосно прашање (query)неПодрачливост 1, најмногу 1.000; повисока страница е 400 invalid_value.
page_countцелосно прашање (query)неРодови по страница. Подрачливо 20, најмногу 100.
start_date
end_date
Структура на прашање (query)неISO 8601 датуми и времиња.
modelСтруктура на прашање (query)неСамо овој модел.
typeСтруктура на прашање (query)неchat, responses, messages, image, video, speech, transcription или embedding.
all_keysБулевар (во прашање)неСо еден клуч: true вклучува секој клуч од ист ним. false.
key_idСтруктура на прашање (query)несо потпишано барање, или со 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 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Тие не се погодени.

Вашиот таен клуч

За да го потпишете, потребен ви е тајниот клуч на вашиот Nim (The Secret Key) 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 листот на апликацијата го покажува на врвот: вашиот јавен клуч, двата баланси, колку клучеви се активни (не се повлечени или истекувани) и Автоматски врв подесувањата, или 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интегритетнеКапацитетот на трошоците во sats, најмалку 1.
reset_periodСтрингнеdaily, weekly или monthlyПотреби limit_satsОставете го надвор за капа што никогаш не се ресетира.
expire_atСтруктура или интегралнеКога клучот престанува да работи: 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 авто-топ-уп

Поврзете го Lightning паричникот со Nostr Wallet Connect и Nymbot самиот ќе го надмине балансот кога трошоците за API го користат ниско. Потпишано барање.

Како функционира: откако барањето за API е наплатено на салдото што сте го одбрале да го гледате, ако тој салдо падна под вашиот праг, Nymbot прави фактура за вашиот износ, бара од вашиот паричник да го плати, и го додава кредитот. Тоа се зголемува најмногу еднаш на секои 5 минути за секој ним и салдо, така што експлозијата на барања не може да го исцеди паричникот. Трошењето во апликациите не го активира. Времето и големината на последниот врв, и последната грешка, се во поставките; ако плаќањето помина по грешка, проверете ја неговата фактура со Статус на врвот Кредит за тоа.

Пред да поврзете паричник

Нимбот го чува шифрирано и само некогаш го користи за да ги плати сопствените фактури, но направи врска само за ова, со буџет за трошење во вашиот паричник, така што најмногу што некогаш може да плати е број избрани од вас. pay_invoice.

Поврзување на паричник

POST https://nymbot.ai/api/v1/nwc-auto-topup/connect Потпишан е

ПолетоТипПотребниОпис на
nwc_urlСтрингДаПриклучокот на лентата, почнувајќи од nostr+walletconnect://Nymbot бара паричник за get_info пред да го зачувате, и да го зачувате шифрирано.
threshold_satsинтегритетДаНагоре кога салдото паѓа под овие многу sats. најмалку 1.000.
topup_satsинтегритетДаКолку да се додаде секој пат. 1.000 до 1.000.000 ставки.
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 Про кредит и заоблени до цела сет (најмалку 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 шестоцифрени знаци. Потоа испратете го истото барање со еден од овие:

СхемаХејдер
Држи 402Authorization: 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-… Покрај тоа, за да се постигне тоа, потребно е да се преземат сите потребни мерки, вклучувајќи ги и мерките за заштита на животната средина (refund_token_sats Во на nymbot Токен вреден помалку од одговорот на барањето 402 refund_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 на Про); стапки кои не прават цела кредит останува на токенот за 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 } }