Skip menyang isi
Kembali menyang Nymbot

Basis kawruh Pembangunan

Keseimbangan, top-ups lan kunci

Check apa sampeyan duwe, top up liwat Lightning, top up otomatis saka dompet dhewe, nonton apa biaya saben permintaan, lan ngatur kunci saka kode.

Nglakoni keseimbangan

Sawetara saka keseimbangan sampeyan, lan sawetara saka kapak kunci iki digunakake.

GET https://nymbot.ai/api/v1/credits/balance Kita kudu nggunakake kunci api. POST Dheweke uga kanggo pelanggan sing ngarepake.

balance iku dua keseimbangan karo ing dolar ing harga Bitcoin saiki, kanggo alat sing ngarepake nomer siji (null ing ngendi harga ora bisa dibaca). sisih ana ing kredit lan sats, kang minangka cara keseimbangan sebenarnya disimpen. key A kunci sing wis nyenengake kapak bisa uga ngetokake keseimbangan.

Jawaban

{
  "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"
  }
}
StatusipunNalika
401Kunci iku munggah, ora dikenal, dibatalake utawa kadu.

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);

Metode pembayaran

Cara sampeyan bisa top up, lan batasan. Lightning iku satu-satunya metode.

GET https://nymbot.ai/api/v1/topup/payment-methods Ngandhakake kunci sing dibutuhake.

A top-up iku 10 kanggo 1.000.000 sats; a Pro top-up kudu beli setidaknya siji Pro kredit, supaya iku miwiti ing 100 sats. bulk_bonus Nulis kredit tambahan ing top-ups gedhe, padha karo ing app: 10%, 15% utawa 20% luwih ing top-ups standar saka 500, 1,000 utawa 5,000 sats, lan ing top-ups Pro saka 5,000, 10,000 utawa 50,000 sats.

Jawaban

{
  "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);

Ngluwi-luwi ing Lightning

Ngasilake tagihan Lightning sing nyedhiyakake kredit kanggo nym sing kunci iku milik. Mbayar saka apa-apa dompet Lightning, banjur Teka ing Dheweke bakal nambah kredit.

POST https://nymbot.ai/api/v1/topup/create/btc-lightning Kita kudu nggunakake kunci api.

Field ikuTiyangDiperlukanDeskripsi
amountNomerya wisIng sawetara, ing currencySampeyan duwe nomer lengkap kanggo sats.
currencyIng stringIngSATS Dheweke bakal nindakake kekosongan. USD lan BTCDollar dikonversi ing harga Bitcoin saiki.
tierIng stringIngpro (Sampunipun dhumateng) utawa standard: apa balanse kredit iku kanggo.

Kredit standar iku 10 sats lan kredit Pro 100 sats, ditambah bonus bulk; credits Ngandika apa ing akun iki bakal nambah.

Jawaban

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "payment_request": "lnbc100u1p5...",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": "2026-09-30T09:27:00Z",
  "status": "pending"
}
StatusipunNalika
400Ing ngisor iki iku: (unsupported_methodIng ngisor iki ana ing ngisor iki (unsupported_currency) utawa tier, jumlah sing kurang, utawa jumlah sing kurang saka minimum (amount_too_small) luwih saka 1 000 000 sats (amount_too_large) utawa ditolak dening dompet Lightning (amount_out_of_range).
429Ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki (rate_limit_exceededDheweke karo Retry-After).
502Tiyang ora bisa diwenehi (invoice_unavailableDheweke karo 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);

Ngudhunakake top-up

Tanya yen invoice wis dibayar lan, sawetara iku, nambah kredit. Checking iku apa kredit iku, supaya sawise pembayaran, ndeleng nganti status iku creditedChecking lagi sawise iku aman: kredit ndhuwur siji, apa sawetara kali sampeyan nggoleki.

GET https://nymbot.ai/api/v1/topup/status/{invoice_id} - perlu kunci saka nym sing nggawe invoice.

status Dheweke pending (Sampunipun ora dibayar) paid (kanggo, nanging ora dikreditake; ndeleng lagi), credited (Ing dhuwur utawa dhuwur) expired (Tidak dibayar ing wektu). medan keseimbangan iku kanggo tingkat sing tagihan topped.

Jawaban

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "status": "credited",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": null,
  "balance_credits": 523.33,
  "balance_sats": 52333
}
StatusipunNalika
400Id iku id 64-karakter saka panggilan nggawe.
404Ing ngisor iki ana ing ngisor iki ana ing ngisor iki ing ngisor iki (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);

Ing sajarah

One baris per permintaan: apa iku, model apa, sawetara token lan apa biaya. No prompts utawa jawaban diwenehi, supaya ora ana dikembalikan. Rows diwenehi kanggo 90 dina, paling anyar pisanan. A kunci sing wis kapanggih kapak bisa uga njaluk sajarah.

GET https://nymbot.ai/api/v1/queries/history — perlu kunci API, sing ndeleng permintaan dhewe, utawa a Panggonan iku ing nyim, kang ndeleng kabeh kunci.

Field ikuTiyangDiperlukanDeskripsi
pageIng ngisor iki (query)IngDefault 1, ing maksimum 1000; kaca luwih dhuwur iku 400 invalid_value.
page_countIng ngisor iki (query)IngRows per page. Default 20, ing maksimum 100.
start_date
end_date
Tiyang (Tiyang)IngISO 8601 tanggal utawa wektu.
modelTiyang (Tiyang)IngSadurunge model iki.
typeTiyang (Tiyang)Ingchat, responses, messages, image, video, speech, transcription lan embedding.
all_keysPiyambak (Piyambak)IngDheweke duwe kunci: true ngandhut kabeh kunci nym sing padha. Default false.
key_idTiyang (Tiyang)IngKanthi panggilan sing ditandatangani, utawa karo all_keys=trueSadurunge kunci iki.

Jawaban

{
  "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);

Panggonan akun

Making, ngganti lan njaluk kunci, ringkasan akun lan top-ups otomatis ora njaluk kunci API. Mereka njaluk tanda saka nym, supaya kunci sing lekat bisa nggunakake nganti capé, nanging ora bisa nggawe kunci liyane utawa njupuk capé dhewe.

Aplikasi ndeleng iki kanggo sampeyan: kabeh ing Neraka Nggunakake titik-titik iki. Sampeyan mung kudu bagian iki kanggo ngatur kunci saka kode dhewe.

Signature iku acara Nostr saka jenis 27235 (NIP-98), dikirim base64-coded ing Authorization Header karo kata Nostr Ing ndhuwur :

Ing acara

{
  "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 iku URL lengkap permintaan, string query kalebu, akurat minangka dikirim.
  • method Iku iku metode HTTP.
  • payload iku SHA-256 saka badan permintaan raw, ing hex. POST lan PATCHDhèwèké bakal nggunakake basa ing basa ing basa ing basa ing basa ing basa.
  • created_at iki kudu ing 60 detik saka jam server.
  • Tiyang nggunakake ing acara, a GET ing, supaya header sing ditangkap ora bisa diputer. Sign a new one for every request. Add a nonce tag karo nilai acak supaya dua permintaan sing ditandatangani ing detik padha masih beda.
  • Tubuh permintaan sing ditandatangani bisa maksimal 64 KB, lan badan kudu Content-Type: application/json.

Kembali ing acara sing munggah 401 missing_nostr_auth; siji sing kurang dibentuk, kurang ditandatangani, terlalu tua, utawa kanggo URL, metode utawa badan beda ngirim invalid_nostr_authIng ngisor iki, ing basa ing basa ing basa ing basa ing basa ing basa ing basa ing basa ing basa. nostr_auth_replayedKode API sing dikirim menyang titik-titik iki ditolak. tanda tangan iki dicekake sadurunge awak dibaca, lan saben alamat bisa gagal 30 kali ing menit (adres IPv6 dihitung minangka kabeh /64); banjur njupuk 429 Dheweke Retry-After.

Ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki (https://nymbot.ai, https://nymchat.app Ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing sisih, ing sisih, ing sisih, ing sisih, ing sisih, ing sisih, ing sisih. OriginDheweke ora terpengaruh.

Kunci rahasia

Tandatangani kudu kunci rahasia nym (the nsec), kang ngontrol kabeh: identitas, riwayat, lan keseimbangan sampeyan. Sadurunge ngetikake ing script ing mesin sing sampeyan percaya, maca saka lingkungan lan ora ngetikake ing file, lan milih app nalika sampeyan bisa.

Piyambak-piyambak iki nyiptake header. Contoh-contoh pungkasan ing kaca iki nggunakake loro. NOSTR_SECRET_HEXWektu iku digunakake ing Niki alat baris perintah, sing njupuk nsec utawa kunci hex, lan sha256sum Ing 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");
}

Rangkuman akun

Apa lembar API aplikasi nuduhake ing ndhuwur: kunci publik, kedhaftar, sawetara kunci aktif (tanpa dibatalake utawa kedhaftar), lan Top-up lan automatik Setelan, utawa null Nalika server ora nyedhiyakake.

GET https://nymbot.ai/api/v1/account Kita kudu a Panggonan iku.

Jawaban

{
  "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());

Manajemen kunci

Endpoints ing panggonan daftar kunci aplikasi. Panggonan ikuMasing-masing kunci dikembalikan ing formulir iki, kanthi wektu ing ISO 8601 lan jumlah ing sats:

Objek utama

{
  "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 iku cukup kanggo njaluk kunci, nanging ora kanggo nggunakake. Kunci dhewe bakal dikembalikan mung siji, nalika digawe.

Panggonan Kunci

GET https://nymbot.ai/api/v1/keys Tandatangani iku.

Field ikuTiyangDiperlukanDeskripsi
include_revokedPiyambak (Piyambak)IngNgandhut kunci sing diwenehi. Default false.

Jawaban

{ "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);

Nggunakake Kunci

POST https://nymbot.ai/api/v1/keys Tembung ing. balik 201.

Field ikuTiyangDiperlukanDeskripsi
nameIng stringya wis1 kanggo 40 karakter, beda saka kunci aktif liyane (mengabaikan kasus).
limit_satsIngkangIngPiyambakipun nyebat ing panggonan, ndhuwur 1 taun.
reset_periodIng stringIngdaily, weekly lan monthlyKena kudu limit_satsTiyang iku kanggo kapak sing ora reset.
expire_atstring utawa integer.IngNalika kunci nghenti kerja: ISO 8601 wektu, utawa milliseconds wiwit 1970.

Tindaklanju (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"
  }
}
StatusipunNalika
400Nama sing munggah utawa terlalu panjang; nama sing wis digunakake (duplicate_name); cap sing ora minangka nomer utamane saka paling 1; periode reset tanpa cap; kadharan ing pungkasan; medan unknown (unknown_parameter); utawa 25 kunci aktif saiki (too_many_keys).
429Ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki (rate_limit_exceededDheweke karo 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);

Nglumpukake 1 kunci

GET https://nymbot.ai/api/v1/keys/{id} Tandatangani iku.

Kembali {"data": {…}} ing objek utama, utawa 404 key_not_found yen ora ana kunci sampeyan duwe id iki.

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);

Ngganti Kunci

PATCH https://nymbot.ai/api/v1/keys/{id} Tandatangani iku.

Ngirim apa-apa saka name, limit_sats, reset_period lan expire_at, karo aturan sing padha nalika nggawe kunci. null Ing ngisor iki, ing ngisor iki, ing ngisor iki, ing sisih, ing sisih, ing sisih, ing sisih, ing sisih, ing sisih, ing sisih, ing sisih, ing sisih (400 key_revokedTembung ing {"data": {…}} ing objek kunci sing diperbarui.

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);

Nglumpukake kunci

DELETE https://nymbot.ai/api/v1/keys/{id} Tandatangani iku.

Nghenti tombol ing wektu, kanggo apik. iku tetep ing daftar karo revoked_at Tiyang, lan bisa ditemokake karo include_revoked=trueMangguhake kunci sing wis diwenehi respon ing cara padha. Sadurunge paling anyar 50 kunci diwenehi disimpen; sing sadurunge diwenehi nalika kunci liyane diwenehi.

Jawaban

{ "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 lan Auto-top-up

Nghubungake wallet Lightning karo Nostr Wallet Connect lan Nymbot mbukak keseimbangan kanthi dhewe nalika biaya API mbukak. Panggonan iku.

Cara nggunakake: sawise permintaan API dibayarkan menyang saldo sing sampeyan milih kanggo nonton, yen saldo iki wis turun ing ngisor ambane sampeyan, Nymbot nggawe tagihan kanggo jumlah top-up, ngandika dompet kanggo ngbayar, lan nambah kredit. Ngluwihi paling siji saben 5 menit kanggo saben nym lan saldo, supaya bubar permintaan ora bisa nguripake dompet. Menghabiskan ing aplikasi ora nyebabake iku. Waktu lan ukuran top-up pungkasan, lan kesalahan pungkasan, ana ing pengaturan; yen pembayaran wis liwat sawise salah, nindakake tagihan karo Status ing top-up Kredit iku.

Sampeyan nyambungake dompet

A string koneksi ngidini siapa sing ngidini ngandika dompet sampeyan kanggo mbayar. Nymbot nyimpen sing enkripsi lan mung nggunakake kanggo mbayar tagihan top-up dhewe, nanging nggawe koneksi mung kanggo iki, karo anggaran pengeluaran ing dompet sampeyan, supaya paling bisa mbayar iku nomer milih sampeyan. dompet kudu mbantu pay_invoice.

Nglumpukake dompet

POST https://nymbot.ai/api/v1/nwc-auto-topup/connect Tandatangani iku.

Field ikuTiyangDiperlukanDeskripsi
nwc_urlIng stringya wisWektu sambungan, dimulai nostr+walletconnect://Nymbot njaluk dompet kanggo get_info Mugi dheweke nglakokake, lan nglakokake.
threshold_satsIngkangya wisTiyang-tiyang ing panggonan iki, ing panggonan iki kurang saka 1000.
topup_satsIngkangya wisSampeyan ora bisa nyimpen apa-apa. 1000 kanggo 1.000.000 sats.
tierIng stringIngpro (Sampunipun dhumateng) utawa standard: keseimbangan kanggo nonton lan top up.

Jawaban

{
  "data": {
    "connected": true,
    "threshold_sats": 5000,
    "topup_sats": 20000,
    "tier": "pro",
    "last_topup_at": null,
    "last_topup_sats": null,
    "last_error": null
  }
}
StatusipunNalika
400Ing ngisor iki ana ing baris (invalid_nwc_urlIng ngisor iki ana ing ngisor iki ana ing ngisor iki (nwc_unreachable) utawa ditolakake kontrol (nwc_rejected); koneksi ora bisa mbayar tagihan (nwc_missing_permission); utawa jumlah liyane saka batasan.
501Ing ngisor iki ana ing server (nwc_unavailable) Sama berlaku kanggo dua titik akhir liyane.

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());

Maca ing settings

GET https://nymbot.ai/api/v1/nwc-auto-topup Tandatangani iku.

Ngirimake obyek sing padha karo nyambungake, karo connected: false Lan lapangan liyane null ing ngendi ora ada dompet disambungake. string sambungan dhewe ora dikembalikan.

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());

Ngluwihi

DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection Tandatangani iku.

Nghapus string koneksi sing disimpen. Tidak luwih top-ups digawe. Kanggo yakin, sampeyan uga bisa ngganti koneksi ing dompet.

Jawaban

{ "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());

Pay per request tanpa kunci

Endpoints harga tetap bisa dibayar kanggo siji permintaan ing wektu liwat Lightning, tanpa kunci, ora akun lan ora saldo: POST /images/generations, POST /images/edits, POST /videos, POST /audio/speech, POST /audio/transcriptions, POST /audio/translations lan POST /embeddingsChat, Jawaban, lan Panggonan uga kudu kunci. Panggonan sing ngangkut kunci dihitung ing saldo minangka biasa; aliran pembayaran mung dimulai nalika ora kunci dikirim.

Nymbot ngandika dua versi saka ide sing padha, saka backend siji: Lightning Labs' Ing 402 (Ing ngisor iki ana ing panggonanipun, LSAT) lan draft IETF Panggonan HTTP authentication ing sistem lightning Metode lan charge Wektu iku nggunakake apa sing klien ngerti.

Ngudhunakake server dhewe

Mbayar tanpa kunci iku mung ing nalika API_L402_SECRET Ngandhut paling 32 byte acak, minangka hex (64 karakter) utawa base64 (44). openssl rand -hex 32Nilai sing luwih pendek utawa bisa ditebak ngaktipake fitur lan nglogke mengapa. API_L402_SECRET_PREVIOUS kanggo siji dinten: credentials, status URL lan tantangan sing digawe ing ngisor iki terus ngoperasikake nganti dadi.

Tantangan iku

Ngirim permintaan karo no Authorization ing header. yen valid, ora ana apa-apa, lan sampeyan njaluk 402 Payment Required karo tagihan kanggo apa persis apa biaya permintaan: harga sing padha kunci bakal mbayar, diwenehi ing 10 sats kredit standar utawa 100 sats kredit Pro lan diwenehi nganti sat kabeh (minimum 1 sat, lan minimal 0.05 kredit minimum). WWW-Authenticate Masalah kanggo akun sing padha:

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 }
}

Panggonan request Parameter iku base64url JSON: {"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.

Piyambakipun nglakoni masalah ing akhir, ing Content-Type (tipe media lan, kanggo multipart, batasan) lan kanggo SHA-256 saka body bytes sing akurat sampeyan ngirim, lan tetep 15 menit. Identitasipun Kira-kira ora lagi: iku padha Content-Type lan bytes JSON padha, utawa kanggo titik-titik akhir multi-part (/images/edits, /audio/transcriptions, /audio/translationsKebanyakan perpustakaan HTTP milih batasan anyar saben kali sing ngkodekake formulir, supaya ngkodekake siji kali lan ngirim bajet iki dua kali.

Kabeh alamat bisa njaluk 30 tantangan per menit (adres IPv6 nghitung minangka total /64). Requests kang alamat ora dikenal njaluk luwih ketat 10 per menit, lan ana cap umum ing tantangan Nymbot masalah ing kabeh alamat; permintaan ditolak sadurunge tantangan digawe (misal karo body sing ora valid JSON) ora nghitung kanggo iku. 429 Dheweke Retry-AfterEndpoints dibayar panggilan tanpa kunci utawa credential uga dihitung menyang batas umum saka 120 permintaan unauthenticated per menit per alamat. Content-Type Iki ora application/json (Ing multipart/form-data Ing ngisor iki, ing ngisor iki uga ditolak. 415 Dheweke ora duwe akun.

Embeddings dipatokake saka estimasi token ing input, karo margin 1.5×, amarga nomer nyata iki mung dikenal sadurunge. Sampeyan mbayar kanggo token nyata digunakake, lan bagian ora digunakake saka pembayaran mbukak minangka Sampeyan token.

Ngirim pembayaran

Mbayar tagihan karo dompet Lightning. Dompet nyedhiyakake preimage, 64 karakter hex. banjur ngirim permintaan padha karo salah siji saka iki:

SistemipunIng header
Ing 402Authorization: L402 <macaroon>:<preimage> (LSAT Dheweke uga dadi)
PanggonanAuthorization: Payment <base64url JSON>Ing ngisor iki, JSON {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}}

Panggonan dibayar nglakoni persis minangka sing digawe karo kunci, nanging nymbot objek ora duwe medan keseimbangan: {"payment": "l402", "tier": "pro", "paid_sats": 237, "charged_sats": 237}Dheweke ora ana X-Nymbot-Balance-Sats Header. Permintaan sing dibayar karo skema Payment uga njaluk Payment-Receipt header (base64url JSON karo id challenge, hash pembayaran minangka reference, status lan timestampPanggonan dibayar ora dikaitake karo nym, supaya padha ora muncul ing riwayat query.

StatusipunNalika
402 payment_already_usedTiyang saben pembayaran bayar kanggo siji permintaan. Jawaban minangka tantangan anyar kanggo permintaan iki, supaya klien sing cache credential pungkasan (seperti lnget Dheweke ndhuwur ndhuwur ndhuwur ndhuwur ndhuwur.
402 payment_mismatchPiyambakipun nyebat ing titik-titik liyane. Content-Type utawa badan, utawa mbayar kurang saka permintaan iki saiki biaya. Tantangan anyar kanggo permintaan iki datang karo; yen pembayaran terlalu cilik, apa sing sampeyan mbayar mbukak minangka Sampeyan token (refund_token lan refund_sats Ing awakipun iku).
402 payment_expiredMinangka luwih saka 15 menit wiwit tantangan. Tantangan anyar datang karo iki. Yen preimage nuduhake sampeyan dibayar, apa sing sampeyan dibayar mbukak minangka Sampeyan token (refund_token lan refund_sats ing tubuh), siji kali; credential banjur digunakake.
401 invalid_preimagePreimage ora hash kanggo pembayaran hash saka faktur. pembayaran ora digunakake.
401 invalid_payment_credentialCredential iku malformed, diganti sawise Nymbot ngirimake, utawa jeneng hash pembayaran Nymbot ora ngirim tagihan kanggo. A macaroon karo caveat Nymbot ora ngerti, utawa karo caveats konflik, ditolak.
429 rate_limit_exceededLebih saka 30 credentials utawa kunci sing gagal kanggo verifikasi datang saka alamat iki ing menit, utawa siji token pengembalian dikirim luwih saka 60 kali ing menit. 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"));

Klien dibangun ing mppx karo metode Lightning nglakoni Panggonan pembayaran dhewe; tunjukake ing titik akhir lan ninggalake.

Video lan

Dheweke dibayar POST /videos Jawaban 202 Ing ngisor iki, plus a status_url: GET iku tanpa kunci kanggo nyimpen tugas. iki ditandatangani lan kerja kanggo 24 jam, nalika tugas iki disimpen.

{
  "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..."
  }
}

Tiyang iku refund_token ing respon iki: iku mung ditampilake ing iki. iku kosong nalika video render (GET /api/v1/l402/refunds Jawaban "status": "pending"); yen render gagal dibutuhake, pembayaran ndhuwur ing iku. URL status nuduhake refund_sats kanggo kerja dikembalikan nanging ora token, supaya ngandhingake URL status ora ngandhingake pengembalian.

Tembungake

Yen permintaan dibayar gagal lan penyedia tagihan Nymbot kanggo percobaan, pembayaran disimpen lan kesalahan ngandika iku, karo charged_satsIng wektu iki, ing wektu iki, ing wektu iki, ing wektu iki, ing wektu iki, ing wektu iki, ing wektu iki. Sampeyan token Ngerti apa sing dibayar:

{
  "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"
  }
}

Bagean sing ora digunakake mbukak ing cara padha: yen sampeyan nggoleki dua gambar lan siji gagal unfilling, respon sukses nymbot obyek nyimpen token pengembalian kanggo sing mungke; transkrip sing panjang ora bisa dibaca ing pra-ditulisake kanggo paling panjang file bisa (kurang luwih saka 30 menit), lan beda kanggo panjang nyata mbukak minangka token pengembalian; yen dadi luwih saka 30 menit, iku ditolak karo 413 Ing ngisor iki, sampeyan bakal nindakake apa-apa, lan kabeh pembayaran mbukak. Embeddings mbukak apa estimasi mbukak. A video gagal mbukak token sing ngirim.

Token pengembalian dhuwit punika kode 256-bit acak. Nymbot nyimpen mung hash-nya, lan iku kadhapake ing 30 dina. Ngandhut saldo sat, lan sampeyan bisa:

  • Mbayar karo iku. Ngirim Authorization: Bearer REFUND-… Ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki, ing ngisor iki (refund_token_sats Ing nymbot Objek). Token sing kurang saka jawaban permintaan 402 refund_insufficient; kegagalan unbiled ndadekake sats ing token sing padha.
  • Teka iku. GET /api/v1/l402/refunds Ing ngisor iki ana ing header. {"sats": 237, "status": "open", "expires_at": "..."}.
  • Token sing bisa digunakake ing maksimum 60 kali ing menit.
  • Nglumpukake ing nym. Nggunakake ing Nggawé hadiah ing aplikasi Nymbot, utawa panggilan POST /api/v1/l402/refunds/redeem lan a Panggonan iku lan {"refund_token": "REFUND-...", "balance": "standard"} (Ing "pro"Total kredit ndadekake saldo (10 sats saben ing standar, 100 ing Pro); sats sing ora nggawe kabeh kredit tetep ing token kanggo permintaan 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"

Jawaban

{ "data": { "credited": 23, "tier": "standard", "balance_credits": 123, "remaining_sats": 7 } }