Lewati ke konten
Kembali ke Nymbot

Basis pengetahuan pengembang

Keseimbangan, top-ups dan kunci

Periksa apa yang Anda miliki, unggul atas Lightning, unggul secara otomatis dari dompet Anda sendiri, lihat berapa biaya setiap permintaan, dan mengelola kunci dari kode.

Memeriksa Keseimbangan

Kedua-dua keseimbangan anda, dan berapa banyak cap kunci ini digunakan.

GET https://nymbot.ai/api/v1/credits/balance Anda membutuhkan kunci api. POST Ini juga berlaku untuk klien yang mengharapkannya.

balance adalah dua keseimbangan bersama dalam dolar pada harga Bitcoin saat ini, untuk alat yang mengharapkan angka tunggal (null Jika harga tidak dapat dibaca). sisanya dalam kredit dan sats, yang adalah bagaimana keseimbangan sebenarnya disimpan. key Kunci yang telah mencapai capnya masih dapat memeriksa saldo.

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"
  }
}
StatusnyaKapan
401Kunci hilang, tidak diketahui, dibatalkan atau habis.

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

Bagaimana Anda bisa naik, dan batas-batas. petir adalah satu-satunya metode.

GET https://nymbot.ai/api/v1/topup/payment-methods Tidak diperlukan kunci.

Top-up adalah 10 hingga 1.000.000 sats; Pro top-up harus membeli setidaknya satu kredit Pro, jadi dimulai pada 100 sats. bulk_bonus daftar kredit tambahan pada top-up yang lebih besar, sama seperti dalam aplikasi: 10%, 15% atau 20% lebih pada top-up standar dari 500, 1.000 atau 5.000 sats, dan pada top-up Pro dari 5.000, 10.000 atau 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);

Berdiri di atas Lightning

Membuat tagihan Lightning yang menambahkan kredit ke nym yang kunci milik. membayarnya dari dompet Lightning, kemudian Periksa itu Untuk mendapatkan kredit tambahan.

POST https://nymbot.ai/api/v1/topup/create/btc-lightning Anda membutuhkan kunci api.

BidangJenisDiperlukandeskripsi
amountJumlahYaBerapa banyak, dalam currencyJumlah keseluruhan untuk taruhan.
currencyStringnyaTidakSATS (Dalam hal yang demikian, USD atau BTCDolar dikonversi pada harga Bitcoin saat ini.
tierStringnyaTidakpro (dalam hal yang demikian) atau standard: ke mana saldo kredit pergi.

Kredit standar adalah 10 sats dan kredit Pro 100 sats, ditambah bonus bulk apa pun; credits Katakan apa saja yang akan ditambahkan ke akun ini.

Jawaban

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "payment_request": "lnbc100u1p5...",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": "2026-09-30T09:27:00Z",
  "status": "pending"
}
StatusnyaKapan
400Metode lain dalam jalur (unsupported_method, sebuah mata uang yang tidak diketahui (unsupported_currency(Baca juga: Harga Minimal, Harga Minimal, Harga Minimal atau Harga Minimal)amount_too_small(lebih dari 1 juta orang)amount_too_large) atau ditolak oleh dompet Lightning (amount_out_of_range).
429Lebih dari 60 faktur untuk nym ini, atau 120 dari alamat ini, dalam satu jam (rate_limit_exceeded, dengan Retry-After).
502Tidak ada yang bisa dilakukan saat ini (invoice_unavailable, dengan 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);

Memeriksa Top-Up

Menanyakan apakah tagihan telah dibayarkan dan, setelah itu, menambahkan kredit. memeriksa apa yang kreditnya, jadi setelah membayar, memeriksa sampai status creditedPeriksa lagi setelah itu aman: kredit mendarat sekali, tidak peduli berapa kali Anda meminta.

GET https://nymbot.ai/api/v1/topup/status/{invoice_id} - membutuhkan kunci dari nym yang membuat faktur.

status adalah pending (Sudah tidak dibayar lagi) paid (terbayar, tetapi belum dikreditkan; periksa lagi), credited (dalam hal yang demikian) atau expired (tidak dibayar tepat waktu). medan keseimbangan adalah untuk tingkat yang tagihan tertinggi.

Jawaban

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "status": "credited",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": null,
  "balance_credits": 523.33,
  "balance_sats": 52333
}
StatusnyaKapan
400ID bukanlah id 64-karakter dari panggilan yang dibuat.
404Tidak ada tagihan oleh id untuk nym Anda (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);

Menginginkan Sejarah

Satu baris per permintaan: apa itu, model apa, berapa banyak token dan berapa biaya. Tidak ada prompts atau jawaban yang disimpan, sehingga tidak ada yang dikembalikan. Baris disimpan selama 90 hari, terbaru pertama. Kunci yang telah mencapai capnya masih dapat membaca sejarahnya.

GET https://nymbot.ai/api/v1/queries/history membutuhkan kunci API, yang melihat permintaan sendiri, atau Menandatangani permohonan dari nymmu, yang melihat setiap kunci.

BidangJenisDiperlukandeskripsi
pageUntuk pertanyaan (query)TidakDefault 1, maksimum 1.000; halaman yang lebih tinggi adalah 400 invalid_value.
page_countUntuk pertanyaan (query)TidakRantai per halaman. Default 20, dengan maksimum 100.
start_date
end_date
Menggunakan string (query)TidakISO 8601 tanggal atau waktu.
modelMenggunakan string (query)TidakHanya model ini saja.
typeMenggunakan string (query)Tidakchat, responses, messages, image, video, speech, transcription atau embedding.
all_keysPerbedaan Boolean (Query)Tidakdengan satu kunci: true termasuk setiap kunci dari nym yang sama.Default false.
key_idMenggunakan string (query)TidakDengan permintaan yang ditandatangani, atau dengan all_keys=trueHanya kunci ini saja.

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

Menandatangani permintaan akun

Membuat, mengubah dan membatalkan kunci, ringkasan akun dan top-up otomatis tidak mengambil kunci API. Mereka mengambil tanda tangan dari nym Anda, sehingga kunci yang bocor dapat menghabiskan hingga capnya tetapi tidak pernah dapat membuat kunci lain atau menaikkan capnya sendiri.

Aplikasi ini melakukan ini untuk Anda: semuanya dalam api yang Anda hanya perlu bagian ini untuk mengelola kunci dari kode Anda sendiri.

Tanda tangan adalah peristiwa Nostr jenis 27235 (NIP-98), dikirim base64-koded di Authorization Header dengan kata Nostr Di depan :

peristiwa tersebut

{
  "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 adalah URL lengkap dari permintaan, string kueri termasuk, persis seperti yang dikirim.
  • method Ini adalah metode HTTP.
  • payload adalah SHA-256 dari badan permintaan mentah, dalam hex. POST Dan PATCH, dan tubuh yang Anda kirimkan harus bajet untuk bajet yang Anda hash.
  • created_at harus berada dalam waktu 60 detik dari jam server.
  • Setiap peristiwa bekerja sekali, a GET termasuk, sehingga header yang ditangkap tidak dapat diputar ulang. Tandatangani yang baru untuk setiap permintaan. Tambahkan nonce tag dengan nilai acak sehingga dua permintaan yang ditandatangani dalam detik yang sama masih berbeda.
  • Tubuh permintaan yang ditandatangani dapat maksimal 64 KB, dan tubuh membutuhkan Content-Type: application/json.

Peristiwa yang hilang kembali 401 missing_nostr_authSalah satu yang buruk terbentuk, buruk ditandatangani, terlalu tua, atau untuk URL yang berbeda, metode atau tubuh mengembalikan invalid_nostr_authdengan alasan dalam pesan; satu yang digunakan kembali nostr_auth_replayedTanda tangan diperiksa sebelum tubuh dibaca, dan setiap alamat dapat gagal 30 kali per menit (alamat IPv6 dihitung sebagai seluruhnya /64); setelah itu ia mendapatkan 429 dengan Retry-After.

Browser dapat menghubungi titik akhir ini hanya dari situs web Nymbot sendiri (https://nymbot.ai, https://nymchat.app Sebuah halaman di situs lain tidak mendapatkan headers CORS kembali, sehingga tidak dapat membaca apa yang mereka kembalikan. OriginMereka tidak terpengaruh.

Kunci Rahasia Anda

Menandatangani membutuhkan kunci rahasia nym Anda (yang nsec), yang mengendalikan segalanya: identitas Anda, riwayat Anda, dan saldo Anda. hanya meletakkannya dalam skenario pada mesin yang Anda percayai, baca dari lingkungan daripada menulisnya ke dalam file, dan lebih memilih aplikasi ketika Anda bisa.

Penolong-penolong ini membangun header. contoh-contoh selanjutnya di halaman ini menggunakan mereka. Mereka membaca kunci rahasia dalam hex dari NOSTR_SECRET_HEXcURL yang satu ini menggunakan Nak alat baris perintah, yang mengambil kunci nsec atau hex, dan sha256sum Untuk 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");
}

Akuntansi Pendekatan

Apa yang ditampilkan di atas lembar API aplikasi: kunci publik Anda, kedua keseimbangan, berapa banyak kunci yang aktif (tidak dibatalkan atau kedaluwarsa), dan Top-up otomatis pengaturan, atau null Jika server tidak menyediakan.

GET https://nymbot.ai/api/v1/account membutuhkan a Menandatangani permohonan.

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

Titik akhir di balik daftar kunci aplikasi. mereka semua membutuhkan Menandatangani permohonanSetiap kunci dikembalikan dalam bentuk ini, dengan waktu dalam ISO 8601 dan jumlah dalam sats:

Objek Kunci

{
  "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 Kunci tersebut cukup untuk mengenali kunci tetapi tidak untuk menggunakannya. Kunci itu sendiri hanya dikembalikan sekali, ketika dibuat.

Daftar Kunci

GET https://nymbot.ai/api/v1/keys yang ditandatangani.

BidangJenisDiperlukandeskripsi
include_revokedPerbedaan Boolean (Query)TidakTermasuk kunci yang dibatalkan. 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);

Membuat Kunci

POST https://nymbot.ai/api/v1/keys Menandatangani. kembali 201.

BidangJenisDiperlukandeskripsi
nameStringnyaYa1 sampai 40 karakter, berbeda dari kunci aktif lainnya Anda (mengabaikan kasus).
limit_satsIntegrasiTidakPengeluaran dalam sats, setidaknya 1. tinggalkan untuk tidak cap.
reset_periodStringnyaTidakdaily, weekly atau monthlyKebutuhan limit_satsTinggalkan untuk cap yang tidak pernah reset.
expire_atstring atau integerTidakKetika kunci berhenti bekerja: ISO 8601 waktu, atau milisekunder sejak 1970.

Jawabannya (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"
  }
}
StatusnyaKapan
400Nama yang hilang atau terlalu panjang; nama yang sudah digunakan (duplicate_name(Baca juga: Cara Menghilangkan Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejala Gejalaunknown_parameter); atau 25 kunci aktif sudah (too_many_keys).
429Lebih dari 60 kunci yang dibuat oleh nym ini, atau 120 dari alamat ini, dalam satu jam (rate_limit_exceeded, dengan 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);

Membaca satu kunci

GET https://nymbot.ai/api/v1/keys/{id} yang ditandatangani.

Kembali {"data": {…}} dengan objek kunci, atau 404 key_not_found jika tidak ada kunci Anda yang memiliki id tersebut.

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

Mengubah Kunci

PATCH https://nymbot.ai/api/v1/keys/{id} yang ditandatangani.

Kirimkan salah satu name, limit_sats, reset_period Dan expire_at, dengan aturan yang sama seperti ketika membuat kunci. null Tidak ada perubahan, tidak ada perubahan, tidak ada perubahan, tidak ada perubahan, tidak ada perubahan, tidak ada perubahan (400 key_revoked) Kembali {"data": {…}} dengan objek kunci yang 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);

Membatalkan Kunci

DELETE https://nymbot.ai/api/v1/keys/{id} yang ditandatangani.

Menghentikan kunci pada saat yang sama, untuk kebaikan. tetap dalam daftar dengan revoked_at ditempatkan, dan dapat dilihat dengan include_revoked=trueMembatalkan kunci yang sudah dibatalkan menjawab dengan cara yang sama. hanya 50 kunci yang paling baru dibatalkan disimpan; yang lebih tua dihapus ketika kunci lain dibatalkan.

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

Spesifikasi NWC Auto-top-up

Menghubungkan dompet Lightning dengan Nostr Wallet Connect dan Nymbot memunculkan keseimbangan dengan sendirinya ketika pengeluaran API berjalan rendah. lembar API aplikasi memiliki pengaturan yang sama; ini adalah titik akhir di belakangnya. Menandatangani permohonan.

Cara kerjanya: Setelah permintaan API dihitung ke saldo yang Anda pilih untuk menonton, jika saldo itu telah jatuh di bawah ambang batas Anda, Nymbot membuat tagihan untuk jumlah top-up Anda, meminta dompet Anda untuk membayarnya, dan menambahkan kredit. Ini mencakup paling banyak sekali setiap 5 menit untuk setiap nym dan saldo, sehingga ledakan permintaan tidak dapat menguras dompet. Menghabiskan di aplikasi tidak memicu itu. Waktu dan ukuran top-up terakhir, dan kesalahan terakhir, berada dalam pengaturan; jika pembayaran berlalu setelah kesalahan, periksa tagihan dengan Status Top-Up kredit untuk itu.

Sebelum Anda menghubungkan dompet

Sebuah string koneksi memungkinkan siapa pun yang memilikinya meminta dompet Anda untuk membayar. Nymbot menyimpannya dienkripsi dan hanya pernah menggunakannya untuk membayar tagihan top-up sendiri, tetapi membuat koneksi hanya untuk ini, dengan anggaran pengeluaran di dompet Anda, sehingga yang paling bisa membayar adalah nomor yang Anda pilih. dompet harus mendukung pay_invoice.

Menghubungkan Dompet

POST https://nymbot.ai/api/v1/nwc-auto-topup/connect yang ditandatangani.

BidangJenisDiperlukandeskripsi
nwc_urlStringnyaYaRantai koneksi, dimulai nostr+walletconnect://Nymbot meminta dompet untuk get_info sebelum disimpan, dan menyimpannya dikodekan.
threshold_satsIntegrasiYaTop up ketika saldo jatuh di bawah ini banyak sats. setidaknya 1.000.
topup_satsIntegrasiYaBerapa banyak yang harus ditambahkan setiap kali. 1.000 sampai 1.000.000 sats.
tierStringnyaTidakpro (dalam hal yang demikian) atau standard: keseimbangan untuk menonton dan 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
  }
}
StatusnyaKapan
400Tidak ada koneksi string (invalid_nwc_url(Baca juga: Cara Menghilangkan Jerawat Dengan Cepat)nwc_unreachable) atau menolak pemeriksaan (nwc_rejected(Baca juga: Cara Menghilangkan Jerawat Tidak Dapat Mengatasi Jerawat)nwc_missing_permissionatau jumlah yang melampaui batas.
501Perangkat lunak ini tidak dapat diakses secara otomatis (nwc_unavailableHal yang sama berlaku untuk dua titik akhir lainnya.

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

Membaca pengaturan

GET https://nymbot.ai/api/v1/nwc-auto-topup yang ditandatangani.

Mengembalikan objek yang sama dengan menghubungkan, dengan connected: false dan bidang lainnya null ketika tidak ada dompet yang terhubung. string koneksi itu sendiri tidak pernah 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());

Disconnect

DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection yang ditandatangani.

Menghapus string koneksi yang disimpan. Tidak ada lagi top-up yang dibuat. Untuk memastikan, Anda juga dapat membatalkan koneksi di dompet Anda.

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

Pembayaran atas permintaan tanpa kunci

Titik akhir harga tetap dapat dibayar untuk satu permintaan pada satu waktu selama Lightning, tanpa kunci, tanpa akun, dan tanpa saldo: POST /images/generations, POST /images/edits, POST /videos, POST /audio/speech, POST /audio/transcriptions, POST /audio/translations Dan POST /embeddingsPermintaan yang membawa kunci dihitung ke saldo seperti biasanya; aliran pembayaran hanya dimulai ketika tidak ada kunci yang dikirim.

Nymbot berbicara dua versi dari gagasan yang sama, dari satu backend: Lightning Labs ' LK402 (juga diterima di bawah nama lama, LSATdan Rencana IETF Pembayaran Autentikasi HTTP dengan lightning Metode dan charge Gunakan apa pun yang dipahami klien Anda.

Mengoperasikan server Anda sendiri

Pembayaran tanpa kunci hanya dimulai ketika API_L402_SECRET memegang setidaknya 32 byte acak, seperti hex (64 karakter) atau base64 (44). openssl rand -hex 32Nilai yang lebih pendek atau dapat diprediksi mematikan fitur dan mencatat mengapa. API_L402_SECRET_PREVIOUS untuk satu hari: credentials, status URL dan tantangan yang dibuat di bawahnya terus bekerja sampai kedaluwarsa.

Tantangan yang

Kirim permintaan dengan tidak Authorization header. jika valid, tidak ada yang berjalan, dan Anda mendapatkan 402 Payment Required dengan faktur untuk persis apa yang biaya permintaan: harga yang sama kunci akan membayar, dikonversi pada 10 sats kredit standar atau 100 sats kredit Pro dan diakhiri hingga seluruh sat (setidaknya 1 sat, dan setidaknya 0.05 minimum kredit). WWW-Authenticate Permasalahan yang dihadapi dalam perhitungan yang sama:

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

Pembayaran request Parameter yang digunakan adalah base64url JSON: {"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.

Sebuah tantangan terikat pada titik akhir, pada Content-Type (tipe media dan, untuk multipart, batasnya) dan ke SHA-256 dari body bytes yang tepat yang Anda kirim, dan berlangsung 15 menit. identik Permintaan yang sama: sama Content-Type dan byte JSON yang sama, atau untuk beberapa titik akhir bagian (/images/edits, /audio/transcriptions, /audio/translationsKebanyakan pustaka HTTP memilih batas baru setiap kali mereka mengkodekan formulir, jadi mengkodekannya sekali dan mengirimkan bajet itu dua kali.

Setiap alamat dapat meminta 30 tantangan per menit (adres IPv6 dihitung sebagai seluruhnya /64). Permintaan yang alamatnya tidak diketahui berbagi 10 yang lebih ketat per menit, dan ada batas keseluruhan pada tantangan Nymbot masalah di semua alamat; permintaan yang ditolak sebelum tantangan dibuat (misalnya dengan tubuh yang tidak valid JSON) tidak dihitung ke arahnya. 429 dengan Retry-AfterTitik akhir yang dibayar yang dipanggil tanpa kunci atau credential juga dihitung ke batas umum 120 permintaan yang tidak terautentikasi per menit per alamat. Content-Type Tidaklah application/json ( atau multipart/form-data yang ditolak (dengan 415 Dan tidak pernah menerima tagihan.

Embeddings dihitung dari perkiraan token dalam input, dengan margin 1,5 kali, karena jumlah sebenarnya hanya diketahui setelahnya. Pengembalian Token.

mengirimkan pembayaran

Bayar tagihan dengan dompet Lightning apa pun. dompet memberi Anda preimage, 64 karakter hex. Kemudian kirim permintaan yang sama dengan salah satu dari ini:

SkemaHeader yang
LK402Authorization: L402 <macaroon>:<preimage> (LSAT juga bekerja)
PembayaranAuthorization: Payment <base64url JSON>Di mana JSON berada {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}}

Sebuah permintaan berbayar menjawab persis seperti yang dilakukan dengan kunci, kecuali bahwa nymbot objek tidak memiliki bidang keseimbangan: {"payment": "l402", "tier": "pro", "paid_sats": 237, "charged_sats": 237}Dan ada tidak X-Nymbot-Balance-Sats Header. permintaan yang dibayarkan dengan skema Pembayaran juga mendapatkan Payment-Receipt header (base64url JSON dengan id tantangan, hash pembayaran sebagai reference, status Dan timestampPermintaan berbayar tidak terikat dengan nym apa pun, sehingga mereka tidak muncul dalam riwayat kueri.

StatusnyaKapan
402 payment_already_usedSetiap pembayaran membayar untuk satu permintaan. tanggapan adalah tantangan baru untuk permintaan ini, sehingga klien yang mencocokkan kredensial terakhirnya (seperti lnget Tentu saja, negara ini hanya sekali lagi.
402 payment_mismatchKeterangan yang dikeluarkan untuk titik akhir lainnya, Content-Type atau badan, atau membayar kurang dari permintaan ini sekarang biaya. tantangan baru untuk permintaan ini datang dengan itu; jika pembayaran terlalu kecil, apa yang Anda bayar kembali sebagai Pengembalian Token (refund_token Dan refund_sats di dalam tubuhnya)
402 payment_expiredLebih dari 15 menit berlalu sejak tantangan. tantangan baru datang dengan itu. jika preimage menunjukkan Anda membayar, apa yang Anda bayar kembali sebagai Pengembalian Token (refund_token Dan refund_sats dalam tubuh), sekali; credential kemudian digunakan.
401 invalid_preimagePreimage tidak hash ke tagihan tagihan tagihan.
401 invalid_payment_credentialCredential yang salah, telah diubah setelah Nymbot menerbitkannya, atau nama hash pembayaran Nymbot tidak pernah mengeluarkan tagihan untuk.
429 rate_limit_exceededLebih dari 30 kredensial atau kunci yang gagal untuk memverifikasi datang dari alamat ini dalam satu menit, atau satu token pengembalian uang dikirim lebih dari 60 kali dalam satu 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 yang dibangun mppx dengan metode Lightning menangani tantangan Pembayaran sendiri; tunjukkan mereka di titik akhir dan biarkan mereka membayar.

Video yang

yang dibayar POST /videos Jawaban 202 Seperti yang disebutkan di atas, plus a status_url: GET Ini ditandatangani dan bekerja selama 24 jam, selama pekerjaan disimpan.

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

Tetaplah yang refund_token Dari hasil pemeriksaan tersebut, hasil pemeriksaan hanya dapat dilihat pada saat pemeriksaan (GET /api/v1/l402/refunds Jawaban "status": "pending"); jika render gagal dibebankan, pembayaran mendarat di atasnya. refund_sats untuk pekerjaan yang dikembalikan tetapi tidak pernah token, jadi berbagi URL status tidak berbagi pengembalian.

Pengembalian

Jika permintaan berbayar gagal dan penyedia menghitung Nymbot untuk percobaan, pembayaran disimpan dan kesalahan mengatakan demikian, dengan charged_sats, persis seperti untuk permintaan kunci. Jika gagal tanpa dihitung, kesalahan membawa Pengembalian Token Nilai yang Anda bayarkan:

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

Bagian-bagian yang tidak digunakan kembali dengan cara yang sama: jika Anda meminta dua gambar dan satu gagal dibebankan, jawaban sukses nymbot objek membawa token pengembalian dana untuk yang hilang; transkrip yang panjangnya tidak dapat dibaca di depan harga untuk yang paling lama file bisa (tidak lebih dari 30 menit), dan perbedaan dengan panjang sebenarnya kembali sebagai token pengembalian dana; jika ternyata lebih lama dari 30 menit, itu ditolak dengan 413 Embeddings mengembalikan apa yang diperkirakan ditahan kembali. video yang gagal mengembalikan token pengiriman yang dikembalikan.

Token pengembalian dana adalah kode acak 256-bit. Nymbot hanya menyimpan hashnya, dan berakhir setelah 30 hari.

  • Bayar dengan itu. Kirimkan Authorization: Bearer REFUND-… (Baca juga: Cara Menghilangkan Jerawat dengan Cepat, Cara Menghilangkan Jerawat dengan Cepat, Cara Menghilangkan Jerawat dengan Cepat)refund_token_sats Di dalam nymbot Token yang bernilai kurang dari jawaban permintaan 402 refund_insufficientKegagalan yang tidak dihitung menempatkan sats kembali pada token yang sama.
  • Periksa saja GET /api/v1/l402/refunds dengan header yang sama kembali {"sats": 237, "status": "open", "expires_at": "..."}.
  • Satu token dapat digunakan hingga 60 kali per menit.
  • Pindahkan ke nym. masukkan ke dalam Buatlah Hadiah dalam aplikasi Nymbot, atau panggilan POST /api/v1/l402/refunds/redeem Dengan a Menandatangani permohonan Dan {"refund_token": "REFUND-...", "balance": "standard"} ( atau "pro"Seluruh kredit pergi ke saldo (10 sats masing-masing pada standar, 100 pada Pro); sats yang tidak membuat seluruh kredit tinggal di token untuk 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 } }