Siirry sisältöön
Palaa sivulle Nymbot

Tietopohja Kehittäjät

Tasapaino, top-ups ja avaimet

Tarkista, mitä sinulla on, ylitä Lightning, ylitä automaattisesti omasta lompakostasi, katso, mitä kukin pyyntö maksaa ja hallitse avaimia koodista.

Tarkista tasapaino

Molemmat tasapainoja, ja kuinka paljon tämän avaimen korkki käytetään.

GET https://nymbot.ai/api/v1/credits/balance Tarvitset vain API-avaimen POST Se toimii myös asiakkaille, jotka odottavat sitä.

balance on kaksi tasapainoa yhdessä dollareissa nykyisellä Bitcoin-hinnalla työkaluille, jotka odottavat yhtä numeroa (null Jos hinta ei ole luettavissa). loput ovat luottoja ja sats, mikä on, miten saldot todella pidetään. key Avain, joka on saavuttanut kynnyksensä, voi silti tarkistaa tasapainon.

Vastaus

{
  "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"
  }
}
TilanneMilloin
401Avain on puuttuva, tuntematon, peruutettu tai vanhentunut.

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

Maksutavat

Miten voit ylittää, ja rajat. salama on ainoa menetelmä.

GET https://nymbot.ai/api/v1/topup/payment-methods Avainta ei tarvita.

Top-up on 10 - 1 000 000 satsia; Pro-top-upin on ostettava vähintään yksi Pro-luotto, joten se alkaa 100 satsista. bulk_bonus luetellaan ylimääräinen luotto suuremmilla top-ups, sama kuin sovelluksessa: 10%, 15% tai 20% enemmän standardin top-ups 500, 1000 tai 5000 sats, ja Pro top-ups 5000, 10,000 tai 50,000 sats.

Vastaus

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

Kiipeä yli salaman

Luo Lightning-laskun, joka lisää luottoa avaimelle. maksa se mistä tahansa Lightning-lompakosta, sitten Tarkista se luottoa on lisätty.

POST https://nymbot.ai/api/v1/topup/create/btc-lightning Tarvitset vain API-avaimen

kenttäTyyppiVaadittuKuvaus
amountMääräKylläKuinka paljon, kun currencyYksi kokonaisluku satsille.
currencyStringissäEiSATS (Tämä on epäonnistumista USD tai BTCDollarit muunnetaan nykyisellä Bitcoin-hinnalla.
tierStringissäEipro (Päätöksen mukaan) tai standard: mihin tasapainoon luotto menee.

Tyypillinen luotto on 10 satsia ja Pro-luotto 100 satsia, plus kaikki tukkubonukset; credits Se kertoo, mitä tämä lasku lisää.

Vastaus

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "payment_request": "lnbc100u1p5...",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": "2026-09-30T09:27:00Z",
  "status": "pending"
}
TilanneMilloin
400Toinen menetelmä polulla (unsupported_method) tuntematon valuutta (unsupported_currency) tai taso, puuttuva määrä tai vähimmäismäärä (amount_too_small) yli 1 000 000 satsin (amount_too_large) tai hylätään Lightning-lompakon avulla (amount_out_of_range).
429Yli 60 laskua tästä nymistä tai 120 tästä osoitteesta tunnissa (rate_limit_exceeded, jossa Retry-After).
502Tällä hetkellä ei voi tehdä laskua (invoice_unavailable, jossa 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);

Tarkista top-up

Kysyy, onko lasku maksettu ja, kun se on, lisää luottoa. Tarkista, mitä luottoa se on, joten maksamisen jälkeen tarkista, kunnes tila on creditedTarkistaminen uudelleen sen jälkeen on turvallista: luotto laskeutuu kerran, riippumatta siitä, kuinka monta kertaa kysyt.

GET https://nymbot.ai/api/v1/topup/status/{invoice_id} - tarvitset avaimen nimestä, joka teki laskun.

status on pending (ei ole vielä maksettu) paid (maksettu, mutta ei vielä luotettu; tarkista uudelleen), credited (joka on tasapainossa) tai expired (ei maksettu ajoissa). Tase-kentät ovat tasolle, jonka lasku ylittää.

Vastaus

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "status": "credited",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": null,
  "balance_credits": 523.33,
  "balance_sats": 52333
}
TilanneMilloin
400ID ei ole luodun puhelun 64-merkkinen ID.
404Ei ole tiliä tuon id: n kanssa nymille (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);

Haluamme historiaa

Yksi rivi per pyyntö: mitä se oli, mikä malli, kuinka monta tokenia ja mitä se maksoi. Ei pyyntöjä tai vastauksia säilytetään, joten mitään ei palauteta. Riviä säilytetään 90 päivän ajan, uusin ensin. Avain, joka on saavuttanut enimmäismääränsä, voi silti lukea historiansa.

GET https://nymbot.ai/api/v1/queries/history — tarvitsee API-avaimen, joka näkee omat pyyntönsä, tai Allekirjoitettu pyyntö Nimi, joka näkee jokaisen avaimen.

kenttäTyyppiVaadittuKuvaus
pageYhteenveto kyselystä (query)EiOletusarvo 1, enintään 1000; korkeampi sivu on 400 invalid_value.
page_countYhteenveto kyselystä (query)EiSivua kohti rivejä. Oletusarvo 20, enintään 100.
start_date
end_date
Pyyntöjä (Query Strings)EiISO 8601 päivämäärät ja ajat.
modelPyyntöjä (Query Strings)EiVain tämä malli.
typePyyntöjä (Query Strings)Eichat, responses, messages, image, video, speech, transcription tai embedding.
all_keysTyylikäs (Query)EiYhden avaimen kanssa: true sisältää jokaisen saman nym:n avaimen. false.
key_idPyyntöjä (Query Strings)Eiallekirjoitetulla hakemuksella tai all_keys=trueVain tämä avain.

Vastaus

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

Tilin allekirjoittamista koskevat pyynnöt

Avainten luominen, muuttaminen ja peruuttaminen, tilin yhteenveto ja automaattiset top-upit eivät ota API-avainta. He ottavat allekirjoituksen nimeltäsi, joten vuotettu avain voi viettää jopa sen päähän, mutta ei voi koskaan tehdä toista avainta tai nostaa omaa päätä.

Sovellus tekee tämän puolestasi: kaikki Paloa Sheet käyttää näitä päätepisteitä. Tarvitset vain tämän osion hallita avaimia omasta koodistasi.

Allekirjoitus on Nostr-tapahtuma tyypin 27235 (NIP-98), joka lähetetään base64-koodattu Authorization Header Sanan kanssa Nostr ja edessä:

Tapahtuman

{
  "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 on pyynnön koko URL-osoite, kyselysarja mukana, täsmälleen lähetetyllä tavalla.
  • method Tämä on HTTP-menetelmä
  • payload on SHA-256 raaka pyyntö kehon, hex. Se vaaditaan POST ja PATCH, ja lähettämäsi kehon on oltava byte per byte, jonka olet hashed.
  • created_at Se on oltava 60 sekunnin sisällä palvelimen kellosta.
  • Jokainen tapahtuma toimii kerran, a GET sisältyy, joten tallennettua otsikkoa ei voi toistaa uudelleen. Allekirjoita uusi kutakin pyyntöä varten. nonce merkitä satunnaisella arvolla niin, että samassa sekunnissa allekirjoitetut kaksi pyyntöä ovat edelleen erilaisia.
  • Allekirjoitetun pyynnön ruumis voi olla enintään 64 KB, ja ruumis tarvitsee Content-Type: application/json.

Kadonnut tapahtuma palaa 401 missing_nostr_authyksi, joka on huonosti muodostettu, huonosti allekirjoitettu, liian vanha tai eri URL-osoitteelle, menetelmälle tai keholle palauttaa invalid_nostr_auth, jossa on viestin syy; uudelleenkäytetty palauttaa nostr_auth_replayedAllekirjoitus tarkistetaan ennen kehon lukemista, ja jokainen osoite voi epäonnistua 30 kertaa minuutissa (IPv6-osoite lasketaan kokonaisuutena /64); sen jälkeen se saa 429 kanssa Retry-After.

Käyttäjät voivat soittaa näihin päätepisteisiin vain Nymbotin omilta sivustoilta (https://nymbot.ai, https://nymchat.app Sivusto ei saa CORS-otsikoita takaisin, joten se ei voi lukea sitä, mitä ne palauttavat. Origineivät ole vaikuttaneet.

Sinun salainen avain

Allekirjoittaminen tarvitsee nimesi salaisen avaimen (nimeä nsec), joka ohjaa kaikkea: identiteettiäsi, historiaasi ja taseesi. Laita se vain skriptiin tietokoneeseen, johon luotat, lue se ympäristöstä sen sijaan, että kirjoittaisit sen tiedostoon, ja mieluummin sovellus, kun voit.

Nämä avustajat rakentavat otsikon. Tämän sivun myöhemmät esimerkit käyttävät niitä. He lukevat salaisen avaimen hexissä NOSTR_SECRET_HEX; cURL yksi käyttää Nainen komentosarjan työkalu, joka ottaa nsec- tai hexavaimen, ja sha256sum ja 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");
}

Tilin yhteenveto

Mitä sovelluksen API-lehti näyttää yläosassa: julkinen avain, molemmat tasapainot, kuinka monta avainta on aktiivisia (ei peruutettu tai vanhentunut) ja Automaattinen top-up Asetukset tai null kun palvelin ei tarjoa niitä.

GET https://nymbot.ai/api/v1/account Tarvitaan a Allekirjoitettu pyyntö.

Vastaus

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

Avainten hallinta

Sovelluksen avainluettelon takana olevat päätepisteet.Kaikki ne tarvitsevat Allekirjoitettu pyyntöJokainen avain palautetaan tällä lomakkeella, jossa on aika ISO 8601: ssä ja summat sats:

Avain kohde

{
  "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 Riittää, että tunnistat avaimen, mutta et käytä sitä.Oma avain palautetaan vain kerran, kun se on tehty.

Avainten luettelo

GET https://nymbot.ai/api/v1/keys ja allekirjoittanut

kenttäTyyppiVaadittuKuvaus
include_revokedTyylikäs (Query)EiSisältää peruutetut avaimet. Default false.

Vastaus

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

Avaimen tekeminen

POST https://nymbot.ai/api/v1/keys Allekirjoittaminen, paluu 201.

kenttäTyyppiVaadittuKuvaus
nameStringissäKyllä1–40 merkkiä, jotka poikkeavat muista aktiivisista avaimista (tapauksen sivuuttaminen).
limit_satsintegroituaEiVähintään 1 kappaletta, jätä se pois ilman kappaletta.
reset_periodStringissäEidaily, weekly tai monthlyTarvitaan limit_satsJätä se pois kannelle, joka ei koskaan palauta.
expire_atstring tai integerEiKun avain lakkaa toimimasta: ISO 8601 aika, tai millisekunnit vuodesta 1970.

Vastaukset (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"
  }
}
TilanneMilloin
400Puuttuva tai liian pitkä nimi; jo käytössä oleva nimi (duplicate_name); kynnys, joka ei ole kokonaisluku vähintään 1; palautusjakso ilman kynnystä; vanhentuminen menneisyydessä; tuntematon kenttä (unknown_parameter); tai 25 aktiivista avainta jo (too_many_keys).
429Yli 60 avainta, jotka tämä nym, tai 120 tästä osoitteesta, teki tunnissa (rate_limit_exceeded, jossa 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);

Yhden avaimen lukeminen

GET https://nymbot.ai/api/v1/keys/{id} ja allekirjoittanut

Takaisin {"data": {…}} avainobjektin kanssa tai 404 key_not_found jos sinulla ei ole tätä tunnusta.

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

Vaihda avain

PATCH https://nymbot.ai/api/v1/keys/{id} ja allekirjoittanut

Lähetä joku name, limit_sats, reset_period ja expire_atSamat säännöt kuin avaimen antamisessa. null poistaa kentän: ei päätä, ei palautetta, ei vanhentumisaikaa. Palautusjakson muuttaminen aloittaa uuden jakson nollalla.400 key_revoked) Takaisin {"data": {…}} päivitetty avainobjekti.

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

Avaimen peruuttaminen

DELETE https://nymbot.ai/api/v1/keys/{id} ja allekirjoittanut

Pysäyttää avaimen välittömästi, hyvä. Se pysyy luettelossa revoked_at asennettu, ja sitä voidaan nähdä include_revoked=trueVain uusimmat 50 peruutettua avainta säilytetään; vanhemmat poistetaan, kun toinen avain peruutetaan.

Vastaus

{ "data": { "id": "4f0c9a1be27d3856", "revoked": true } }

cURL

URL=https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856
curl -X DELETE "$URL" -H "Authorization: $(nostr_auth DELETE "$URL")"

Python

import requests

url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856"
print(requests.delete(url, headers={"Authorization": nostr_auth("DELETE", url)}).json())

JavaScript

const url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856";
const res = await fetch(url, { method: "DELETE", headers: { "Authorization": nostrAuth("DELETE", url) } });
console.log(await res.json());

NWC Auto-top-up Näytä tarkat tiedot

Yhdistä Lightning-lompakko Nostr Wallet Connectin kanssa ja Nymbot nostaa tasapainon itsestään, kun API-menot ovat alhaiset. sovelluksen API-lehden asetukset ovat samat; nämä ovat sen takana olevat päätepisteet. Allekirjoitettu pyyntö.

Miten se toimii: kun API-pyyntö lasketaan katsomaan valitsemallesi saldolle, jos saldo on pudonnut kynnyksesi alapuolelle, Nymbot laatii laskun ylimääräisestä summastasi, pyytää lompakkoasi maksamaan sen ja lisää luottoa. Se ylittää enintään kerran 5 minuutin välein jokaiselle nimelle ja saldolle, joten pyyntöjen räjähdys ei voi tyhjentää lompakkoa. Sovelluksissa käytettävät kulut eivät käynnistä sitä. Viimeisen ylimäärän ja viimeisen virheen aika ja koko ovat asetuksissa; jos maksu meni läpi virheen jälkeen, tarkista lasku Top-up asema ja luottaa siihen.

Ennen kuin liität lompakon

Nymbot tallentaa sen salattu ja vain koskaan käyttää sitä maksaa omia top-up laskuja, mutta tehdä yhteys vain tätä varten, kulutuksen budjetin lompakossa, joten eniten se voisi koskaan maksaa on numero valitsi sinut. lompakko on tukea pay_invoice.

Yhdistä lompakko

POST https://nymbot.ai/api/v1/nwc-auto-topup/connect ja allekirjoittanut

kenttäTyyppiVaadittuKuvaus
nwc_urlStringissäKylläLiitäntälinja, joka alkaa nostr+walletconnect://Nymbot pyytää lompakkoa get_info ennen sen tallentamista, ja tallentaa sen salattuina.
threshold_satsintegroituaKylläHuippua, kun saldo laskee alle tämän monen satsin.
topup_satsintegroituaKylläKuinka paljon lisätä joka kerta. 1 000 - 1 000 000 sats.
tierStringissäEipro (Päätöksen mukaan) tai standard: tasapaino tarkkailla ja ylös.

Vastaus

{
  "data": {
    "connected": true,
    "threshold_sats": 5000,
    "topup_sats": 20000,
    "tier": "pro",
    "last_topup_at": null,
    "last_topup_sats": null,
    "last_error": null
  }
}
TilanneMilloin
400Ei ole yhteysmerkkiä (invalid_nwc_url); lompakko ei vastannut lähetykseen (nwc_unreachable) tai kieltäytynyt tarkastuksesta (nwc_rejected); yhteys ei voi maksaa laskuja (nwc_missing_permission) tai määrä, joka on rajojen ulkopuolella.
501Automaattiset yläkohdat eivät ole käytössä tässä palvelimessa (nwc_unavailableSama pätee myös muihin kahteen päätepisteeseen.

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

Lue asetukset

GET https://nymbot.ai/api/v1/nwc-auto-topup ja allekirjoittanut

Palauttaa samat objektit kuin yhteys, jossa connected: false ja muut kentät null Kun lompakkoa ei ole kytketty, itse yhteysmerkkiä ei koskaan palauteta.

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

Rajoittaminen

DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection ja allekirjoittanut

Poistaa tallennetun yhteyssarjan. Ei enää ylityksiä. Varmista, että voit myös peruuttaa yhteyden lompakossasi.

Vastaus

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

Maksaminen pyynnöstä ilman avainta

Kiinteän hinnan päätepisteitä voidaan maksaa yhdestä pyynnöstä kerrallaan Lightningin aikana ilman avainta, tiliä ja saldoa: POST /images/generations, POST /images/edits, POST /videos, POST /audio/speech, POST /audio/transcriptions, POST /audio/translations ja POST /embeddingsChat, vastaukset ja viestit tarvitsevat aina avaimen. Avainta sisältävä pyyntö laskutetaan saldolle tavalliseen tapaan; maksuvirta alkaa vasta, kun avainta ei lähetetä.

Nymbot puhuu kahdesta versiosta samasta ideasta, yhdestä taustasta: Lightning Labs' L402 Näytä (tunnetaan myös vanhan nimensä mukaan) LSAT) ja IETF-luonnos maksuun HTTP Authentication -järjestelmä lightning Menetelmää ja charge Käytä mitä asiakas ymmärtää.

Käytä omaa palvelinta

Maksaminen ilman avainta on käytössä vain, kun API_L402_SECRET sisältää vähintään 32 satunnaista merkkiä, kuten hex (64 merkkiä) tai base64 (44). openssl rand -hex 32Lyhyempi tai arvattavissa oleva arvo poistaa ominaisuuden käytöstä ja kirjautuu, miksi. API_L402_SECRET_PREVIOUS Päivä: luottokortit, tilan URL-osoitteet ja sen mukaisesti tehdyt haasteet toimivat, kunnes ne vanhenevat.

Haasteen

Lähetä pyyntö ei Authorization jos se on pätevä, mikään ei toimi, ja saat 402 Payment Required laskun kanssa täsmälleen mitä pyyntö maksaa: sama hinta, jonka avain maksaisi, muunnetaan 10 satsilla vakio-luottoon tai 100 satsilla Pro-luottoon ja pyöristetään kokonaiseksi satiksi (vähintään 1 sat, ja vähintään 0.05 luotto vähimmäismäärä). WWW-Authenticate Ongelmat samassa laskussa:

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

Maksaminen request Parametri on base64url JSON: {"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.

Haaste on sidottu päätepisteeseen, Content-Type (mediatyyppi ja usean osan osalta sen raja) ja SHA-256: lle lähettämäsi tarkka kehon bytejä, ja kestää 15 minuuttia. identtinen Pyyntö uudelleen: sama Content-Type ja samat JSON-baitit, tai useiden osien päätepisteiden osalta (/images/edits, /audio/transcriptions, /audio/translationsUseimmat HTTP-kirjastot valitsevat uuden rajan joka kerta, kun ne koodaavat lomakkeen, joten koodaa se kerran ja lähetä nämä bytit kahdesti.

Jokainen osoite voi pyytää 30 haastetta minuutissa (IPv6-osoite laskee kokonaisuutena /64). Pyynnöt, joiden osoite ei ole tiedossa, jakavat tiukemman 10 minuutissa, ja Nymbot-haasteiden kokonaismäärä on kaikissa osoitteissa; pyyntö, joka hylätään ennen haasteen tekemistä (esimerkiksi ruumiilla, joka ei ole voimassa JSON) ei laske sitä kohti. 429 kanssa Retry-AfterMaksettuja päätepisteitä, joita kutsutaan ilman avainta tai luottokelpoisuutta, lasketaan myös kohti yleistä rajaa 120 ei-todennettuja pyyntöjä minuutissa per osoite. Content-Type Ei ole application/json (tai multipart/form-data kieltäytymisestä) on kielletty 415 Koskaan ei saa laskua.

Sisäänrakennukset hinnoitellaan syötetyn tokenin arvioinnista, jonka marginaali on 1,5 kertaa, koska todellinen luku tunnetaan vasta sen jälkeen. Takaisin Token.

Maksun lähettäminen

Maksat laskun millä tahansa Lightning-lompakolla. Lompakko antaa sinulle esikuvan, 64 kuudetta merkkiä.

JärjestelmäHeaderit
L402 NäytäAuthorization: L402 <macaroon>:<preimage> (LSAT toimii myös
maksuunAuthorization: Payment <base64url JSON>, jossa JSON on {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}}

Maksullinen pyyntö vastaa täsmälleen samalla tavalla kuin avaimella tehty pyyntö, paitsi että nymbot Objektilla ei ole tasapainokenttiä: {"payment": "l402", "tier": "pro", "paid_sats": 237, "charged_sats": 237}Ja siellä ei ole X-Nymbot-Balance-Sats Header. Maksuohjelmalla maksettu pyyntö saa myös Payment-Receipt header (base64url JSON kanssa haaste id, maksu hash kuin reference, status ja timestampMaksetut pyynnöt eivät ole sidoksissa mihinkään nimmiin, joten ne eivät näy kyselyhistoriassa.

TilanneMilloin
402 payment_already_usedJokainen maksu maksaa yhden pyynnön. vastaus on uusi haaste tähän pyyntöön, joten asiakas, joka tallentaa viimeisen luottokorttinsa (kuten lnget Jälleen kerran vain maata.
402 payment_mismatchLuottoluokitus on annettu toiselle päätepisteelle, Content-Type tai keho, tai maksaa vähemmän kuin tämä pyyntö nyt maksaa. Uusi haaste tähän pyyntöön tulee sen kanssa; jos maksu oli liian pieni, mitä maksoit palaa takaisin Takaisin Token (refund_token ja refund_sats ja kehon sisällä).
402 payment_expiredHaasteesta on kulunut yli 15 minuuttia. Uudenlainen haaste tuo mukanaan. Jos esikuvassa näkyy, että olet maksanut, se, mitä olet maksanut, palaa takaisin. Takaisin Token (refund_token ja refund_sats Ruumiissa) kerran; luotettavuus on sitten käytetty.
401 invalid_preimageEsikuva ei sisällä laskun maksuhashia.
401 invalid_payment_credentialLuottokelpoisuus on epämuodostunut, se on muutettu sen jälkeen, kun Nymbot on antanut sen, tai nimittää maksuhash Nymbot ei ole koskaan antanut laskua. makaron, jolla on varoitus, jota Nymbot ei tiedä tai jossa on ristiriitaisia varoituksia, hylätään.
429 rate_limit_exceededYli 30 tunnusta tai avainta, joita ei voitu vahvistaa, tuli tältä osoitteelta minuutissa tai yksi palautusmerkki lähetettiin yli 60 kertaa minuutissa. 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"));

Asiakkaat ovat rakentaneet mppx Lightning-menetelmällä käsitellään itse maksutapahtumaa; osoita heidät päätepisteeseen ja anna heidän maksaa.

Videoita

ja maksettu POST /videos vastauksia 202 kuin yksi avain, plus a status_url: GET Se on allekirjoitettu ja toimii 24 tuntia, niin kauan kuin työ pidetään.

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

Pidä se refund_token Vastaa tähän vastaukseen: se näkyy vain tässä. Se on tyhjä, kun taas video toistaa (GET /api/v1/l402/refunds vastauksia "status": "pending"); jos suoritus epäonnistuu veloittamatta, maksu laskeutuu siihen. refund_sats palautettuun työhön, mutta ei koskaan tokeniin, joten tilan URL-osoitteen jakaminen ei jaa palautusta.

Palautukset

Jos maksettu pyyntö epäonnistuu ja palveluntarjoaja veloittaa Nymbotin yrityksestä, maksu pidetään ja virhe sanoo niin, charged_satsJos se epäonnistuu ilman laskutusta, virhe aiheuttaa Takaisin Token Se on sen arvoista mitä olet maksanut:

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

Käyttämättömät osat palautuvat samalla tavalla: jos pyysit kahta kuvaa ja yksi epäonnistui, onnistunut vastaus nymbot objekti kantaa palautusmerkkiä puuttuvalle; transkripti, jonka pituutta ei voitu lukea etukäteen, hinnoitellaan niin kauan kuin tiedosto voisi olla (ei koskaan yli 30 minuuttia), ja ero todelliseen pituuteen tulee takaisin palautusmerkkina; jos se osoittautuu olevan pidempi kuin 30 minuuttia, se hylätään 413 ja koko maksu palautetaan. Sisällöt palauttavat sen, mitä arvio pidettiin takaisin. Epäonnistunut video palauttaa palautetun lähetyksen tunnuksen.

Palautusmerkki on satunnainen 256-bittinen koodi. Nymbot tallentaa vain sen hashin, ja se vanhenee 30 päivän kuluttua.

  • maksaa sen kanssa. Lähetä Authorization: Bearer REFUND-… Yllä olevassa kohdassa (OpenAI SDK ottaa sen API-avaimeksi), hinta tulee tokenista ja jäljellä oleva pysyy siinä (refund_token_sats Niissä nymbot Token, joka on vähemmän arvoinen kuin pyynnön vastaukset 402 refund_insufficient; laskettamaton epäonnistuminen asettaa satsin takaisin samaan tokeniin.
  • Tarkista se GET /api/v1/l402/refunds Samanlainen header palaa {"sats": 237, "status": "open", "expires_at": "..."}.
  • Yksi token voidaan käyttää enintään 60 kertaa minuutissa.
  • Siirrä se nymille. Laita se sisään Palauta lahja Nymbot-sovelluksessa tai soittamalla POST /api/v1/l402/refunds/redeem kanssa a Allekirjoitettu pyyntö ja {"refund_token": "REFUND-...", "balance": "standard"} (tai "pro"Kokonaiset luotot menevät tasapainoon (10 satsia kussakin standardissa, 100 Pro); satsit, jotka eivät tee koko luottoa pysymään tokenissa API-pyyntöihin.

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"

Vastaus

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