Saltatu edukira
Nymbot-era bueltan

Ezagutza oinarria Garapitzaileak

Saldoa, kargak eta giltzak

Ikusi zer duzun, kargatu Lightning bidez, kargatu automatikoki zure portafoiotik, ikusi eskaera bakoitzak zer kostatu zion, eta kudeatu moduluetatik gakoak.

Saldoa egiaztatzen ari naiz

Zure bi saldoak, eta gako hauren gehikorra zenbat erabilita dagoen.

GET https://nymbot.ai/api/v1/credits/balance — API gako bat behar du. POST fungitzen ere egiten du, hori espero duten bezeroentzat.

balance zenbalti bi hauek elkarrekin dolarretan daudela Bitcoinren prezio egokian, zenbaki bakarra espero duten tresnarako (null (zenbakia irakurri ezin bada). Geria guztia kredituetan eta satsetan dago, eta horrela mantentzen dira saldoak benetan. key eskatu zuen gakoa deskribatzen du. Bere limitua iritsi duen gakoak hala ere saldoa egiaztatu dezake.

Erantzuna

{
  "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"
  }
}
EstatusaNoiz
401Gakoa falta da, ezaguna ez da, anulatua da edo arrailatu da.

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

Ordainketa metodoak

Nola gehitu saldoa eta mugak. Lightning izango da metodo bakarra.

GET https://nymbot.ai/api/v1/topup/payment-methods — ez du urrari beharrik.

Sare-kargak 10 eta 1.000.000 satzen artean da; Pro sare-karga batek Pro kreditu bat gutxienez erosi behar du, beraz 100 satzetatik hasten da. Dolar limitak Bitcoinren prezioari jarraitzen diote. bulk_bonus entzusia gehigarria azaltzen du haserriak handiagoetan, aplikazioan bezalaxe: %10, %15 edo %20 gehiago haserri arrunteetan 500, 1.000 edo 5.000 sats-etik aurrera, eta Pro haserrietan 5.000, 10.000 edo 50.000 sats-etik aurrera.

Erantzuna

{
  "supported_methods": [
    {
      "method": "btc-lightning",
      "display_name": "Bitcoin Lightning",
      "supported_currencies": ["SATS", "USD", "BTC"],
      "limits": {
        "SATS": { "min": 10, "max": 1000000 },
        "USD": { "min": 0.02, "max": 1170 },
        "BTC": { "min": 1e-7, "max": 0.01 }
      },
      "tiers": ["standard", "pro"],
      "default_tier": "pro",
      "tier_min_sats": { "standard": 10, "pro": 100 },
      "sats_per_credit": { "standard": 10, "pro": 100 },
      "bulk_bonus": [
        { "bonus": 0.1, "standard_sats": 500, "pro_sats": 5000 },
        { "bonus": 0.15, "standard_sats": 1000, "pro_sats": 10000 },
        { "bonus": 0.2, "standard_sats": 5000, "pro_sats": 50000 }
      ]
    }
  ]
}

cURL

curl https://nymbot.ai/api/v1/topup/payment-methods

Python

import requests

methods = requests.get("https://nymbot.ai/api/v1/topup/payment-methods").json()
print(methods["supported_methods"][0]["limits"])

JavaScript

const methods = await (await fetch("https://nymbot.ai/api/v1/topup/payment-methods")).json();
console.log(methods.supported_methods[0].limits);

Lightning bidezren kargatzea

Lightning faktura bat egiten du nym-ari kidea dagozkion kredituak gehitzeko. Itxi Lightning portafoi edozein erabiltuz, ondoren egiaztatu kreditu hori gehitu izateko.

POST https://nymbot.ai/api/v1/topup/create/btc-lightning — API gako bat behar du.

KaleaIdatziBeharrezkoaDeskribapena
amountzenbakiaBaiZer kantitate, currencyZenbakizur oso bat satsentzat.
currencysariaEzSATS (berezgaia), USD edo BTCDolarrak Bitcoinren prezio egokian bihurtzen dira.
tiersariaEzpro (egoargarria) edo standard: zein saldo biltzen duen kreditu hori.

Kreditu standard bat 10 sats da eta Pro kreditu bat 100 sats, lote bulkiko edozein bonusa gehitu eta; credits faktura honek zer gehituko du dio dio.

Erantzuna

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "payment_request": "lnbc100u1p5...",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": "2026-09-30T09:27:00Z",
  "status": "pending"
}
EstatusaNoiz
400Metodo beste bat bidean (unsupported_method), moneta ezaguna bat (unsupported_currency) edo maila, falta falta falta kopurua, edo minimuma azalerako kopurua (amount_too_small), 1,000,000 sats baino gehiago (amount_too_large) edo Lightning wallet-ek uko egin dien (amount_out_of_range).
429Inozte batetik igaro, faktura 60 baino gehiago antzinako izen honekin, edo 120 antzinako onesibide honekin (rate_limit_exceeded, ,rekin Retry-After).
502Ez da faktura egin ahal orain mascato (invoice_unavailable, ,rekin 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);

Sare-betetzea egiaztatzen ari naiz

Faktura ordaindu den jakin nahi du eta, ordaindu denean, kredituari gehitzen dio. Egiaztapenak dira kredituak ematen dituenak, beraz, ordaindu ondoren, egoera den arte egiaztatu. credited. Berriro egiaztatzea segurua da gero: kredituak behin bakarrik iristen da, zenbat aldiz eskatu ez baduzu.

GET https://nymbot.ai/api/v1/topup/status/{invoice_id} — faktura egin zuen nym-etik giltza bat behar du.

status da pending (oraindik ez pagatu), paid (ordaindu, baina oraindik kreditatuta ez; begiratu berriro), credited (zure saldoan) edo expired (ez da ordaindu garaiz). Saldo-aldia faktura kargatzen den mailarako da.

Erantzuna

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "status": "credited",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": null,
  "balance_credits": 523.33,
  "balance_sats": 52333
}
EstatusaNoiz
400ID ez da sortze deiaren 64 karaktereko IDa.
404Ez dago faktura horretako ID horretarako zure nym-erako (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);

Bilaketa historia

Eskaera bakoitzeko fila bat: zer zen, zein modelo, zenbat token eta zenbat kostatu zen. Ez da promptik edo erantzunetik ez da gordetzen, beraz ez da ezta innone itzuliz. Filak 90 egunetara arte gordetzen dira, berriena lehenik. Bere limitea iritsi duen gako batek bere historia oraindik irakurri dezake.

GET https://nymbot.ai/api/v1/queries/history — API gako bat behar du, bere eskaerak ikusten dituena, edo eskari sinratua zu zure izen sekretuaren bidez, bakoitzaren gakoa ikusten duena.

KaleaIdatziBeharrezkoaDeskribapena
pageentegeroa (bilaketa)EzBerezkoratua 1, gehien 1.000; orri altuago bat da 400 invalid_value.
page_countentegeroa (bilaketa)EzOrrialdeko lerroak. Oinarrizkoa 20, gehienez 100.
start_date
end_date
testuinguru (bilaketa)EzISO 8601 datak edo orduak.
modeltestuinguru (bilaketa)EzModela hau bakarrik.
typetestuinguru (bilaketa)Ezchat, responses, messages, image, video, speech, transcription edo embedding.
all_keysboolean (entzibila)EzTxertarekin: true hamaika izenberdiko izen bakoitzaren gako guztia barne hartzen ditu. Bifazkoa false.
key_idtestuinguru (bilaketa)EzEskaera sinatutako batekin, edo... all_keys=true: gako hau bakarrik.

Erantzuna

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

Kontu eskaerak sinatzea

Gakoak egitea, aldatzea eta ezabatzeko prozesuak, kontu laburpena eta automatikoki eskuetzea ez dute API gako bat behar. Zure nym-etik iristen den sinadura bat behar dute, beraz, filtratutako gako batek bere limitura arte gastatu dezake, baina ez du inoiz beste gako bat egin dezakeen edo bere limitua igota dezakeen.

Aplikazioak hau egiten dizu: dena bere... API orrialdeak endpoint hauek erabiltzen ditu. Zure propioko kodean daudela gakoak kudeatzeko atal hau bakarrik behar duzu.

Sinadura 27235 motako Nostr ekizado bat da (NIP-98), base64 kodatuta bidaltzen dena... Authorization titulua hitza dagoena Nostr aurrean:

Txapelkidea

{
  "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 eskaeraren URL osoa da, eskatzailearen stringa barne, bidali bezala zehaztasun osoan.
  • method HTTP metodoa da.
  • payload eskaera-gorrizkoaren SHA-256a da, hex formatuan. Honetan beharrezkoa da POST eta PATCH, eta bidaltzen duzun korpua byte bakoitzeko bera izan behar du hash egin duzuna.
  • created_at zerbitlaritzaren orduarekin 60 segunduko ezinbesteko margoan egon behar du.
  • Gertakari bakoitza behin egiten da, a GET barne hartua, beraz, hartutako burulegidi bat ez da berrerikatu daitekeena. Sinatu berri bat eskaera bakoitzerako. Gehitu... nonce balio alokatu baten arau ditzake taga berri alokatuarekin, beraz, segundu berean zigunltuak ere desberdinak izan daitezela.
  • Eskakizun sinatutako baten oihala gehieneko 64 KB izan daiteke, eta ohi bati behar dio Content-Type: application/json.

Gertakari galditu bat itzultzen da 401 missing_nostr_auth; formatu txarriakoa, sinadura txarra duena, oso zaharra dena, edo URL, metodo edo kide ezberdin batentzat dagoena, hau itzultzen du invalid_nostr_auth, mezuan arrazoia dagoen ariarekin; berriz erabiltutakoa bueltatzen da nostr_auth_replayed. Honeetako endpointetara bidalitako API gako bat baztertzen da. Azpixatura testugatzen da oihala irakurri baino lehen, eta helbide bakoitzak minutako 30 txan entzun dezake (IPv6 helbide bat bere /64 osoa kontatzen da); horren ostean 429 rekin Retry-After.

Browserek endgameinak hauek Nymbot-en propioko webguneetatik soilik dei ditzakete (https://nymbot.ai, https://nymchat.app eta haien subdomeinetan). Beste edozein webgunean dagoen orrialdeak ez ditu CORS txertakaririk jasotzen, beraz, ezin ditu itzultzen dituenak irakurri. Scriptek eta aplikazio natiboek, ez dituztenek Origin, ez dira afetatu.

Zure gako sekretua

Sinadura honek zure nym-aren gako sekretua behar du (the nsec), dena kontrolatzen duena: zure identitatea, zure historia eta zure saldoa. Ez duzu script batean jarri beharzu zuretzain fidatzen zaren makina batean, ingurunearen bidez irakurri eta ez filean idatzi, eta aplikazioa aukeratu preferentzialki ahal izaten duzun guztian.

Laguntzaile hauek esteka eraikitzen dute. Orrialde honetako ondorengo adibideek haiek erabiltzen dituzte. Hex formatuan dagoen sekretu-gakoa irakurtzen dute NOSTR_SECRET_HEX; cURL-enak erabiltzen du nak komando-lerroko tresna, nsec edo hex gako bat hartzen duena, eta sha256sum (macOS-en, 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");
}

Kontuaren laburpena

Apparen API orrialdeak goialdean erakusten duena: zure sarbide publikoa, saldo bi guztiak, zein gako diren aktiboak (ez benjaminatuak edo irauberritutakoak), eta igoera automatikoa ajurgeriak, edo null zerbitzarrak ez dituen eskaintzen duenean.

GET https://nymbot.ai/api/v1/account — bat behar du eskari sinratua.

Erantzuna

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

Gakoak kudeatzea

App-aren gako zerrendaren atzean dauden puntendiburuak. Guztiak behar dute a sinadu duen eskaria. Gako bakoitza forma honetan itzuliko da, denborak ISO 8601 formatuan eta zenbakierak satsetan:

Objetu gakoa

{
  "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 nahikoa da giltza ezagutzeko, baina ez erabiltzeko. Giltza berera behin bakarrik itzul daiteke, egiten denean.

Teketei zerrendak egitea

GET https://nymbot.ai/api/v1/keys — sinadua.

KaleaIdatziBeharrezkoaDeskribapena
include_revokedboolean (entzibila)EzSartu kendetu ziren gakoak. Lehentzietarako. false.

Erantzuna

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

Gako bat egiten ari naiz

POST https://nymbot.ai/api/v1/keys — sinadua. Itzulitakoak 201.

KaleaIdatziBeharrezkoaDeskribapena
namesariaBai1 eta 40 karakter arteko, zure beste giltza aktiboetatik ezberdina (kasua ez jurtuz).
limit_satsentegeroaEzGastu geharketa batas limitazioa, gutxienez 1. Utzi alkat limitazioa ez badu.
reset_periodsariaEzdaily, weekly edo monthly. Beharrak limit_satsEz behezu inoiz resetatzen ez den tope batentzat.
expire_attestuingurua ala integerraEzGakoa funtzionatzen uzten duenean: ISO 8601 denbora bat, edo milisegundoak 1970tik bertara.

Erantzuna (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"
  }
}
EstatusaNoiz
400Izena falta da edo urすぎる luzea da; izen bat erabiltzen dagoela ere (duplicate_name); gutxienez 1 osagarri osoa ez den tope bat; tope gabeako reset aldia; iraganeko berakhiratzea; talde ezagun bat (unknown_parameter); edo 25 gako aktibo jada (too_many_keys).
429Nym honek egindako 60 giltza baino gehiago, edo helbide honetatik 120, ordu batean (rate_limit_exceeded, ,rekin 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);

Gako bat irakurtzea

GET https://nymbot.ai/api/v1/keys/{id} — sinadua.

Iturriak {"data": {…}} objetdu klaretekin, edo 404 key_not_found ez bada zureren klagatik ez du ID hori.

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

Gako bat aldatzea

PATCH https://nymbot.ai/api/v1/keys/{id} — sinadua.

Bidali edozein name, limit_sats, reset_period eta expire_at, giltza egiten dueneko bezalako arau berdinekin. null txanpa bat garbitzen du eremua: ez dago limitaziorik, ez resetarik, ez expiraziorik. Reset garaiari aldaketa egiteak zeroan bermea berri bat hasten du. Gatziotako gako bat ez da aldatu daitekeela (400 key_revoked). Itzulera {"data": {…}} txertatutako giltza objektuarekin.

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

Gako baten kanporatzea

DELETE https://nymbot.ai/api/v1/keys/{id} — sinadua.

Gakoa berehala gelditzen du, betiko. Zerrendan geratzen da honekin revoked_at hornitu, eta ikus daiteke ...rekin include_revoked=true. Jada anulatua dagoen gako bat anulatzeak modu berean erantzuten du. Anulatutako gako berrienetako 50 soilik gordetzen dira; beste bat anulatzen denean, zaharragoak ezabatzen dira.

Erantzuna

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

Konektatu Lightning portafoi batea Nostr Wallet Connect erekin eta Nymbotek saldoa berez betetzen du API gastuak txikiena iristen denean. Apparen API orrietan doako konfigurazio hauek daude; hauek etaude horren atzean kokatutako endpoint-ak. Guztiak behar dute eskari sinratua.

Modu e maneraetan funtzionatzen du: API eskaera bat zure monitorizazioan saldoa aukeratu duzun eskaeraren kostean kargatzen denean, balansua zure limitagarria baino txikiagoa bada, Nymbot-ek zureren kargapen kopuruaren faktura bat egiten du, zure portafoiari ordain dezala eskatzen dio, eta kreditu hori gehitzen du. 5 minututan behin gehiago kargatzen du nym eta saldo bakoitzarengatik, beraz, eskaera bat-batean egitenak ez du portafoiari ezerna egin dezakeen. Aplikazioetan gastatzeak ez du prozesu hori aktibatzen. Azken kargapenaren unea eta tamaina, eta azken errorea, konfigurazioan daude; errore baten ondoren ordainketa bat egin bada, bere faktura egiaztatzea... egarritzearen egoera Kreditu ematen dio.

Wallet bat konektatu aurretik

Lotura-sormenek nor berek du, zure portafoiak ordaindu dezan eskatzeko aukera ematen dio. Nymbot ordezkatuta gordetzen du eta bere kargak pagatzeko soilik erabiltzen du, baina justo hauentzat lotura bat sortu, zure portafoiako gastu-aurrekontu batekin, beraz, gehien ordain dezakeen zenbakia zureak hautuatutakoa izango da. Portafoiak laguntzea beharrezkoa da pay_invoice.

Portafolio bat konektatzea

POST https://nymbot.ai/api/v1/nwc-auto-topup/connect — sinadua.

KaleaIdatziBeharrezkoaDeskribapena
nwc_urlsariaBaiLotura-saria, hasten da nostr+walletconnect://. Nymbot-ek portafoiari eskatzen dio get_info gorde aurretik, eta enkriptatuta gordetzen du.
threshold_satsentegeroaBaiEgoera hau sartzen denean sartu saldoa honako satts hau errutik beherago dagoenean. Gutxienez 1,000.
topup_satsentegeroaBaiZer kantitate gehitu behar da bakoitzean. 1,000 ate 1,000,000 sats.
tiersariaEzpro (egoargarria) edo standard: saldoa zaindu eta kargatu beharrekoa.

Erantzuna

{
  "data": {
    "connected": true,
    "threshold_sats": 5000,
    "topup_sats": 20000,
    "tier": "pro",
    "last_topup_at": null,
    "last_topup_sats": null,
    "last_error": null
  }
}
EstatusaNoiz
400Ez da konexio-aktibategia (invalid_nwc_url); portafølioak ez zuen erantzun bere errelea bidez (nwc_unreachable) edo egiaztapena uko egin zuen (nwc_rejected); konexioak fakturak ezin ditu ordaindu (nwc_missing_permission); edo muguen kanpoko kantitate bat.
501Sarrerako top-up automatikoak ez daude켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜켜nwc_unavailable). Bera egiten da beste bi puntuko bidezko terminoz ere.

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

Konfigurazioak irakurtzen ari naiz

GET https://nymbot.ai/api/v1/nwc-auto-topup — sinadua.

Konektatzeak ematen duen objektu bera itzultzen du, ...-rekin. connected: false eta beste eremuak null portafolio baten konexioa ez dagoenean. Konexio-saria ez da inoiz entzermaten.

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

Konektatuta uzten ari da

DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection — sinadua.

Konexio-testua gordtzen den stringa ezabatzen du. Ez da gehiago lehentasuna/igoera (top-up) egingo. Ziurtatzeko, zure portafolioan konexioa kendu ere dezakezu.

Erantzuna

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

Eskaera bakoitzeko ordainketa giltzarik gabe

Prezio fikoko terminak Lightning bidez eskaera bat txarretan ordaindu daitezke, giltzarik gabe, konturik gabe eta saldoik gabe: POST /images/generations, POST /images/edits, POST /videos, POST /audio/speech, POST /audio/transcriptions, POST /audio/translations eta POST /embeddings. Txatak, Erantzunak eta Mezuak beti behar dute gako bat. Gako bat daramatzan eskaera ohiko bezala saldu egiten da salduko saldoan; ordainketa fluxoak gako bat bidali ez denean hasi egiten da bakarrik.

Nymbot-ek ideia beraren bertsio bi hitz egiten ditu, backend batetik: Lightning Labs' L402 (hainero ere bere izen zaharrean onartzen dena, LSAT) eta IETF drafta Ordainketa HTTP autentikazio esquema honekin lightning metodoa eta charge asmoa. Erabili zure bezeroak ulertzen duen edozein.

Zure propioa sartzea

Ordainketa giltzarik gabe bakarrik ondu dagoenean API_L402_SECRET gutxienez 32 byte aleatorio du, hex bezala (64 karakter) edo base64 bezala (44). Egiteko bat egin mezuarekin openssl rand -hex 32. Balio labunagoa edo asmatzeko erraza batak eziztu egiten du ezaugarria eta zergatia erregistratzen du. Aldatzeko, balio zaharra mugitu eginzu API_L402_SECRET_PREVIOUS egun batez: izendapenak, egoeraren URLak eta horren bidez egindako erronkak ira egiten duten arte funtzionatzen jarraitzen dute.

Erronka

Bidali eskaera ez dagoen bezala Authorization titulua. Baliozkoa bada, ez da ezer funtzionatzen eta zerbait jasotzen duzu 402 Payment Required eskaera horrek eskatzen duen zenbatekoa zehatz eginez faktura batekin: gako batek ordainduko lukeen irabazi berdinak, 10 sats standard kreditugatik edo 100 sats Pro kreditugatik bihurtuta eta sat oso bateraino goraondoztatua (gutxienez 1 sat, eta gutxienez 0.05 kredituko minimoa). erantzunak hiru darama WWW-Authenticate faktura bera uchun errongak:

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

Ordainketa request parametroa base64url JSON da: {"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.

Zaila dago erronka amaieragatik lotuta, Content-Type (bere media mota eta, multipartentzat, bere muga) eta bidali ditzuen korpuzko byte zehatzen SHA-256-ra, eta 15 minutuko iraupena du. Ordaindu<|image><tool|> identiko berriro eskatu: bera bera Content-Type eta JSON byte berdinak, edo multipart endpoint-entzat (/images/edits, /audio/transcriptions, /audio/translations) hainbat parteko gorputz bera muga bera erabiliz. HTTP liburutegi gehienek muga berri bat hautatzen dute formulario bat kodatzen duten bakoitzean, beraz, kodeatu ezazu behin eta bidali byte horiek bi aldiz.

Helbide bakoitzak minutaren batean 30 erronka eskat ditzake (IPv6 helbide bat bere /64 osoa bezala kontatzen da). Helbidea ez ezaguna den eskaerak minutaren batean 10 eskatzen dituzte, eta Nymbot-ak helbide guztietan erronkak emateko gehieneko muga bat dago; erronka egin baino lehen uko egiten den eskaera bat (adibidez, JSON baliozkoa ez den body baten ondorioz) ez da muga horretan kontatzen. Horretaz haratago erantzuna da 429 rekin Retry-After, ukoez sentia oharrak irakurri baino lehen. Gako edo kredentzia gabe deifikatzen diren puntuak ere kontatzen dira helburu orokorraren barruan: minutako 120 eskaera autentikatu gabeko bidaia zelada bakoitzeko. Kredentzia bat egiaztatzen da oharrak irakurri baino lehen, eta eskaera baten... Content-Type ez da application/json (edo multipart/form-data (ibilgaitzetarako) uko egiten zaio _________________ bidez 415 eta inoiz ez du faktura bat jasotzen.

Embeddings-en prezioa inputeko tokenen estimatetik kalkulatzen da, 1.5× margenarekin, kontatu benetarraa geroago soilik ezagutzen baitzaio, eta token benetan erabiltzen direnengatik ordaintzen duzu, eta ordainketaren parte erabili ez dena itzuliko da... gelduruko tokena.

Ordainketa bidaltzen ari naiz

Ordaindu faktura Lightning wallet edozeinarekin. Walletak preimagea emango dizu, 64 hex karakteretakoa. Ondoren, bide hauetako bat erabiliz eskatza bera bidali:

PlanaTitulua
L402Authorization: L402 <macaroon>:<preimage> (LSAT fungitzen ere egiten du)
OrdainketaAuthorization: Payment <base64url JSON>, non dago JSONa {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}}

Ordainduko eskaera baten erantzuna txertatutako giltzaren batekin egindakoaren beretikakoa da, ez arraia hau izan salbu nymbot objektuak ez ditu saldo-aldareak: {"payment": "l402", "tier": "pro", "paid_sats": 237, "charged_sats": 237}, eta ez dago X-Nymbot-Balance-Sats titulua. A Ordainketa mota horretarekin ordaindu den eskaera batek ere % Payment-Receipt header (base64url JSON erronkiaren IDarekin, ordainketa hasharekin bezala reference, status eta timestamp). Erakarketa ordainduak ez dira izenใดekin lotuta, beraz ez dira agertzen bilaketa historikoan.

EstatusaNoiz
402 payment_already_usedOrdainketa bakoitzak eskaera bat ordaintzen du. Erantzuna eskaera honen erronka berri bat da, beraz, azken kredentzia gordetzen duen bezero bat (bezala lnget berriro ordaintzen du soilik.
402 payment_mismatchIzendapena beste puntendiko batenentzat ematu zen, Content-Type edo gorputza, edo orain eskaera honen kostua honetan baino gutxiago ordaindu du. Eskaera honentzat erronka berri bat dator; ordainketa txikiegia izan bada, ordaindu duena itzultzen da gelduruko tokena (refund_token eta refund_sats gorputzean.
402 payment_expiredErronketik 15 minutu baino gehiago igaro dira. Erronka berri bat datorronik. Preimageak ordaindu duela erakusten badu, ordaindu duzuna itzuli egingo da... bezala gelduruko tokena (refund_token eta refund_sats lainan), behin; orduan kredentiala erabiltuta geratzen da.
401 invalid_preimageAurrez-irudia ez da fakturaren ordainketaren hashera konpondutzen. Ordainketa ez dago erabiltuta.
401 invalid_payment_credentialKredentzialak oker doa, Nymbot-ek emandakoan aldatu da, edo Nymbot-ek faktura inoiz eman ez duen ordainketa-hash bat izendatzen du. Nymbot ez dakien ohar bat duen macaroon bat, edo ohar konfrontatzaileak dituena, baztertuta dago.
429 rate_limit_exceededBerrikuntza edo gako 30 baino gehiagok berifikatzeko ez zuten funtzionatu bertan minuteko tartean, edo pistu baten itzultzeko tokena 60 baino gehiagotan bidali zen minuteko tartean. Itxaron 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"));

Klienteak eraikiak ⇩ mppx Lightning metodo batekin ordainketa erronka kudeatuko dute; puntatuko dituzte amaieragura eta ordaindu erasiko dute.

Bideoak

Ordaindu duena POST /videos erantzunak 202 gakoa duen bezala, eta agindutakoa status_url: GET lanari jarraipen egiteko giltzarik gabe. Sinaturata dago eta 24 ordu funtzionatzen du, lana mantentzen den bitartean.

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

Gorde... refund_token hain honekotik irampen honekin: hemen bakarrik erakusten da. Bideoa prozesatzen den bitartean hutsik dago (GET /api/v1/l402/refunds erantzunak "status": "pending"); rendertzeak fakturagabe huts egiten badu, ordainketa horretan amaitzen da. Egoeraren URLak erakusten du refund_sats lan errefundatu batentzat, baina inoiz ez tokena, beraz egoera URLa partekatzeak ez du errefunda partekatzen. Tokena egiaztatzeak, inork poltsatu ez zuen falla egindako lana ere konpontzen du.

Diru-etorakitzak

Eskaera ordainduak huts egiten badu eta hornitzaileak Nymbot bilgarri hartzen badu saialdiaren trantzean, ordainketa gordetzen da eta erroreak horrela dio, honekin charged_sats, gakoarekin eskatutako baten bera bezala zehazki. Erregistroa ordaindu gabe huts egiten bada, erroreak zerbait darama gelduruko tokena ordaindu duzun balioa:

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

Erabiltzatik gabe gordetako piezak modu berean itzultzen dira: bi irudi eskatu badituzu eta bat fakturatu gabe huts egin badu, arrakasta erantzunaren nymbot objektuak falta denaren erstatetik diru-etorera berpentseko token bat darama; hasieran irakurri ezin izan zen transkripzioaren irauera fitxategiaren irauera gehienaren arabera kobratzen da (30 minututik gehiago ez, inoiz), eta benetako iraurerako aldea diru-etorera berpentseko token gisa itzultzen da; 30 minututik luzagoa dela ikusten badu, errefusatzen da 413 eta ordainketa osoa bueltatzen da. Embedding-ek estimatuek atzera bakoizkoak itzultzen dituzte. Bideo huts batek bere bidalketak itzultzen zuen tokenera eutsi egiten du.

Itzultzeko token bat 256-bitko kode alokatu bat da. Nymbot-ek bere hash-a soilik gordetzen du, eta 30 egun pasatzean prezkatzen da. Sat saldoa du, eta honela egin dezakezu:

  • Itzali horrekin ordaindu. Bidali Authorization: Bearer REFUND-… gozoki horietako edozeinetan (OpenAI SDK batek API gako gisa hartzen du). Prezioa tokenetatik ateratzen da eta geratzen dena horretan geratzen da (refund_token_sats ...en nymbot objektua). Eskaeratik gutxiago balio du tokenak erantzunak 402 refund_insufficient; kobratu gabeako akats batek sat-ak token berean eraiktzen ditu.
  • Begiratu. GET /api/v1/l402/refunds buru berdinarekin itzultzen du {"sats": 237, "status": "open", "expires_at": "..."}.
  • Token bat minuteko 60 aldiz gehien erabili daiteke.
  • Mugitu nym batera. Iontu bertara Egiaztatu regalo bat Nymbot aplikazioan, edo deitu POST /api/v1/l402/refunds/redeem a baten</h4> eskari sinratua eta {"refund_token": "REFUND-...", "balance": "standard"} (edo "pro"). Kreditu osoak saldoan doaz (10 sats bakoitza standard-ean, 100 Pro-n); kreditu oso bat ez egiten duten satsak tokenean geratzen dira API eskaeraentzat.

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"

Erantzuna

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