Nimdeɛ a wɔde gyina so Akanfoɔ a wɔyɛ adwuma a wɔyɛ nneɛma foforɔ
Akonta, m’adɔeɛ ne nneɛma a ɛhia sɛ wɔde ma wo
Hwɛ nea wopɛ, ma owia wɔ Lightning so, ma owia de wo wallet no nso de firi wo nua so, hwɛ sɛnea ɛtɔ sɛ asusuakɔtwe biara, na kã kɔ kwan foforɔ a ɛfiri code mu nso.
Wɔde mfiri na ɛkyerɛ krataafa yi ase sɛnea ɛbɛyɛ a ɛbɛyɛ mmerɛw. Engiresi kasa mu mfitiase de no ne nkyerɛase a ɛfa ho.
Akontaabu mu sika hwɛ
Mo obu mmoa nyinaa, ne sɛnea wɔadi saa kɛseɛ yi anom adidi.
GET https://nymbot.ai/api/v1/credits/balance — hia API key bi. POST ɛyɛ nso, asɛmfɛfoɔ a wɔhwɛ aseɛ no nti.
balance nkyɛn mmienu no nyinaa wura dollars mu wɔ Bitcoin nsuani a ɛwɔ nnɛ yi, ɛde ma
ntuo a wɔhwɛ adidi baako (null sɛ ɔtɔ bere no wɔn ntumi nkyerɛwee a. Ne a ɛka no ne
credits ne sats, ne ara ne sɛnea wɔ hwɛ akontaabu no so kwan so. key ɛkyerɛw kwan no
a ɔbɛtumi afire no. Akwan a ɛahyɛ ne kwan mu no, ɛtumi ahu ne nkyerɛkyerɛmu no bio.
Aboa mu nkyerɛaseɛ
{
"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"
}
}
| Ɛdaeɛ | Ɛberɛ bɛn? |
|---|---|
401 | Akwanhyia no awɔ, yɛnni aseɛ nka, wɔasɛe, anaa ɛakɔ ne ntentan. |
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);
Akɔdeɛ kwan ahorow
Sɛnea wubetumi de sika ahyɛ mu, ne mpanim bi a ɛwɔ so. Lightning ne kwan a ɛtɔ so onipa.
GET https://nymbot.ai/api/v1/topup/payment-methods — kwan biara nni hɔ a ɛhia.
Sika mmoa yɛ 10 kɔsi 1,000,000 sats; Pro mmoa no ɛsɛ sɛ ɛtɔ Pro credit baako anadwo, enti ɛhyɛ aseɛ
fi 100 sats. Dollar limit no nteteeɛ no di Bitcoin nkyenkyereɛ akyi. bulk_bonus ɛkyerɛ mpaebɔ deɛ ɛkɔ so wɔ nkyɛdeɛ kɛseɛ no so, sɛnea ɛwɔ app no mu no: 10%, 15% anaa 20% kɔsoro wɔ standard top-ups a ɛfiri
500, 1,000 anaa 5,000 sats no so, na wɔ Pro top-ups no so nso ɛfiri 5,000, 10,000 anaa 50,000 sats no so.
Aboa mu nkyerɛaseɛ
{
"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 soɔ mpoɔsoɔ
Hye Lightning invoice bi a ɛbɛ de credit hyɛ nym a key no kɔ no mu. Fa any Lightning wallet bi mu bɔ no, na ɛnna hwɛ no sika a ɛwɔ credit no de kɔ sɛ sɛnea ɛbɛyɛ a wɔbɛfa no bɛde to wo mu.
POST https://nymbot.ai/api/v1/topup/create/btc-lightning — hia API key bi.
| Akwantuo kwan | Twerɛ | Ɛsɛ sɛ wɔde di dwuma | Nkyerɛkyerɛmu |
|---|---|---|---|
amount | nɔba | Aane | Ɛtena sɛn, wɔ currency. Nkontaa kɛse bi ma sats. |
currency | ntɛntɛn | Daabi | SATS (nea ɛda hɔ no), USD annaa BTCDɔlaa no wɔde si Bitcoin nnyigyeɛ a ɛwɔ nnɛ yi mu. |
tier | ntɛntɛn | Daabi | pro (deɛ ɛda hɔ no) anase standardƐdeɛn akontaabu mu na kredi no bɛkɔ. |
Adeɛ a ɛkyerɛ adan adan nneɛma ne 10 sats na Pro credit no ne 100 sats, ne nneɛma a ɛsɛ sɛ wɔde nnyɛ pii no nso;
credits Ɛkyerɛ nea saa akontabuo yi bɛhyɛ mu.
Aboa mu nkyerɛaseɛ
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"payment_request": "lnbc100u1p5...",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": "2026-09-30T09:27:00Z",
"status": "pending"
}
| Ɛdaeɛ | Ɛberɛ bɛn? |
|---|---|
400 | Akwan foforɔ bi wɔ kwan no mu (unsupported_method), ɔsika a wɔnnyɛ mmɔden kwan bi (unsupported_currency) anaa tier, adeɛ a ɛhia nka, anaa adeɛ a ɛdi minimum no ase (amount_too_small), mmia sata (sats) a ɛdɔɔ so 1,000,000 (amount_too_large) anaa Lightning wallet no ahyɛɛ mu (amount_out_of_range). |
429 | Invoicesee mmienu sɛ mmienu mmaradidi (60) a ɛsen saa nym yi so, anaa nkyerɛkyerɛmu mmienu (120) firi saa kɔmputa adresi yi firi anopa wɔ ahoɔden kronkron (anɔpa) mu (rate_limit_exceeded, ne Retry-After). |
502 | Ɛnyɛ possible sɛ yɛyɛ invoice biara mfitiaseɛ yi (invoice_unavailable, ne 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);
Mefiri ahosɛefoɔ mu adidi bi ho asɛm
Ɛbɛsu sɛ ekyirde no awɔ sɛ wɔapayɛ no anaa, na sɛ wɔapayɛ no a, ɔbɛhyɛ akredit no mu. Sɛ wɔhwɛ a, ɛno na ɛde akredit no ma, enti a wɔapayɛ no a, hwɛ kɔsi sɛ ne bɔne no bɛyɛ dɛɛdeɛ credited. Sɛ wopɛ sɛ wopɛ mmerɛ bi a, wopɛ nanso ɛnyɛ hu: akontaabu no mu sika no ba ne sɛnea wopɛ kɔkɔɔ biara.
GET https://nymbot.ai/api/v1/topup/status/{invoice_id} — ɛsɛ sɛ ɔnya kɛseɛ firi nym a ɔyɛɛ invoice no no.
status ɛyɛ pending (yɛannua da), paid (Ahyɛ no, nanso ɛnnɔ so ase mma no da; hwɛ bio,) credited (wo akonta mu) anaa expired (ɛnnidi wɔ bere mu). Balance beaeɛ no yɛ ma kɔti a invoice no kɔ so ma no no.
Aboa mu nkyerɛaseɛ
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"status": "credited",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": null,
"balance_credits": 523.33,
"balance_sats": 52333
}
| Ɛdaeɛ | Ɛberɛ bɛn? |
|---|---|
400 | Id no nyɛ ɔdaeɛ no 64-character id a ɛfiri create call no mu. |
404 | Ɛnyɛ wo din (nym) nti na wo ID no mu nnyɛ invoice bi Ɛ🏾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);
Nsɛmuesɛtɔ nkyerɛkyerɛmu
Kɔmɔ biako kɔmɔ biako: nea ɛyɛɛ no, mɔde bɛn, nkyerɛwee (tokens) bɛn, ne nea ɛtee nkwantuoɔ. Nkyerɛkyerɛmu anaa nkyerɛaseɛ biara ntetee, enti obiara nnye bi. Kɔmɔ no wɔ hɔ wɔ nnɔkra aduasa (90 days) mu, nea ɛdi kan ne nea ɛdi akyi. Akwan a ɛahyɛ ne nneyɛe mu mu no, ɛtumi ahu ne nkyerɛkyerɛmu no.
GET https://nymbot.ai/api/v1/queries/history — API key kwan bi na ɛhia, a ɛhwɛ ne nea ɛhwɛ ne ho mpaebɔ no, anaa a asɛm a wɔahyɛ nkyerɛwee wɔ mu efiri wo din no mu, a ɛhwɛ ɔpon kwan biara.
| Akwantuo kwan | Twerɛ | Ɛsɛ sɛ wɔde di dwuma | Nkyerɛkyerɛmu |
|---|---|---|---|
page | integer (asɛmbiɛ) | Daabi | Ɛnyinsɛm 1, ɛnyɛ kɔ a ɛrebɛkɔ sɛ mfonini 1,000; ɛkyɛn saa nkyekyɛmu yi nso ne 400 invalid_value. |
page_count | integer (asɛmbiɛ) | Daabi | Nkyekyɛmu a ɛwɔ afeɛ bi wɔ asɛmhyɛ mu. Ne nkyekyɛmu ne 20, ɛtɔ mmata 100. |
start_dateend_date | string (asɛm asɛ:") | Daabi | ISO 8601 da an anɔpa. |
model | string (asɛm asɛ:") | Daabi | Ɛde saa model yi nkoaa. |
type | string (asɛm asɛ:") | Daabi | chat, responses, messages, image, video, speech, transcription annaa embedding. |
all_keys | boolean (asɛm bi a ɛwɔ mfeɛ mu) | Daabi | Ne adeɛ a ɛtwa ɔpo: true ɛkyerɛ nnyinasoɔ biara a ɛwɔ nkyerɛkyerɛmu a ɛdi kan no mu. Default false. |
key_id | string (asɛm asɛ:") | Daabi | Ne nkyerɛkyerɛmu a wɔate aseɛ no, anaa ne... all_keys=trueKɛsi yi nkoaa. |
Aboa mu nkyerɛaseɛ
{
"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);
Akonta nkyerɛkyerɛmu a wɔrehyɛ aseɛ
Ɛyɛ key anom, asɛm sesa, ne kɔm nkyerɛkyerɛmu ne deɛ ɛyɛ deɛ ɛyɛ deɛ ɛka kɔm nkyerɛkyerɛmu no nyinaa, ɛhia API key biara. Wɔhia w'anym (nym) nkyerɛkyerɛmu (signature), enti sɛ key bi bue a, ɛtumi di dwumadie a ɛda ne nkyerɛkyerɛmu so no, nanso ɛntumi mma no kwan sɛ ɛbɛyɛ kɔm key foforɔ anaa ɛbɛma ne nkyerɛkyerɛmu kɔ so.
App yi yɛ eyi ama wo: biribiara wɔ ne mu API sheet di dwumadie bɔn yi dwuma. Wo nkoaa hia saa kɔmputa da yi sɛnea wubɛtumi adi wo code mu nkyɛdeɛ akyerɛ.
Nnyigye yi yɛ Nostr event a ɛyɛ kind 27235 (NIP-98), a wɔasɛe no wɔ base64-encoded mu wɔ
Authorization ti mu nkyerɛkyerɛmu a ɔwɔ asɛmfua no Nostr anim:
Asɛm no
{
"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ɛyɛ request no URL kɔmɔ no nyinaa, asɛm a wɔde hyɛɛ mu nso, ɛyɛ ne sɛnea wɔde hyɛɛ no kɔmɔ no exactly.methodɛno ne HTTP kwan no.payloadɛno ne raw request body no SHA-256, wɔ hex mu. Yɛhia no wɔPOSTnePATCH, na nea wofiri no mu ne wo nnam no ɛsɛ sɛ ɛyɛ nea ɛyɛɛ no nea woyɛɛ ne kɔm (hash) no mma biara nnyɛ foforɔ.created_atƐsɛ sɛ ɛbɛyɛ mmiɛnsa nante (60 seconds) a ɛbɛkɔ mpo sɛ server no nante.- Adeɛ biara yɛ adwuma birĩ, a
GETwɔde hyɛ mu, enti header a wɔafa no nnyɛ a obi bɛtumi de agye ne ho a. Sian mu nsɛm foforɔ ma request biara. Fa bi addownoncefa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea ɛnyɛ nea ɛwɔ hɔ no nkyɛnfa de fa nkyɛnkyɛn nea - A nkyerɛwee a wɔasɛn no mu bɛtumi ayɛ 64 KB kɛseɛ bi, na nkyerɛwee no hia...
Content-Type: application/json.
Asɛm a ɛkɔɔ bi de ba 401 missing_nostr_auth; nea ɛyɛ mpaa, nea ɛnyɛ nokware, nea ɛda hɔ dodoɔ, anaa nea ɛyɛ URL, method anaa body foforɔ bi nti de ama
invalid_nostr_auth, ne nkyerɛkyerɛmu no wɔ mpaboa no mu; nea wɔ de hyɛɛ no bio no ba bio
nostr_auth_replayedAPI key a wɔatuma hyɛ saa endpoints yi mu no, wɔanya no.
Wɔhwɛ signature no ansa na wɔanante body no ase, na ala adresi biara bɛtumi ayɛ nneɛma a ɛyɛ mpan (fail) 30 wɔ minit mu (IPv6
ala adresi biara kɔ mpaako /64 mu); ɛda saa a, ɛgye 429 ne ho
Retry-After.
Abawafoɔ (Browsers) bɛtumi afa saa endpoints yi dwumadie fi Nymbot nkyerɛwee sɛnea ɛteɛ no nko ara (https://nymbot.ai,
https://nymchat.app (ne wɔn subdomains nso). Wɔ afe biara a ɛwɔ afa bi foforɔ so no, CORS
headers biara nni hɔ a ɛbɛba, enti ɛntumi mmu nea wɔde ba no. Scripts ne native apps, a wɔntumi ntu
Origin, ɛnyɛ wɔn ho asɛm.
Akyerɛkyerɛmu no nnya wo nym ne kɔm kɔm mfonini (ɛno) nsec), a ɛhyɛ biara a ɛwɔ mu: wo din, wo amammere ne wo sika a ɛwɔ wo nsa mu. Fa nkɔmmɔbɔ (script) a wopɛ wɔ kɔmputa a wopɛ ne ho akyerɛ, fa fie (environment) fi kɔmputa no mu na ɛnyɛ sɛ wode to no file mu, na fa app no dwene kɛseɛ bere biara a wubetumi adi.
Ssɛnfoɔ yi si header no ano. Adeɛ a ɛreba mfatoho biara wɔ saa asɛm yi ase no de wɔn adi. Wɔhia secret
key a ɛyɛ hex no firi NOSTR_SECRET_HEX; cURL no deɛ uży Ɛ
nka komputɛ bɔteneɛ kwan, a ɛfa nsec anaa hex
key, na ne... sha256sum (Wɔ macOS so, 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");
}
Akonta mmuaeɛ no
API sheet no mpanim no wɔ app no mu: wo public key, akɔm mmienu no nyinaa, nka sɛ key bɛn na ɛwɔ anim (a wɔankasɛe anaa bi nnwu), ne... deɛ ɛyɛ nokwafoɔ mmerɛ a wɔde mpanin bɔ ho anaa mpanin nnyimpa nkyerɛkyerɛmu ayɛbea no, anaa
null sɛ server no annye wɔn.
GET https://nymbot.ai/api/v1/account — hia mmerɛ bi asɛm a wɔahyɛ nkyerɛwee wɔ mu.
Aboa mu nkyerɛaseɛ
{
"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());
Kɔti hwɛ ne ho
App key list no a ɛhyɛ app no anim no endpoints nyinaa. Wɔtwe nyinaa hia ne a Mpaebɔ a wɔatow nkyerɛwee bi wɔn so. Key biara hyɛ saa fã yi mu, ne bere a ɛwɔ ISO 8601 mu ne nkaano a ɛwɔ sats mu:
Akwanya adeɛ
{
"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 Ɛyɛ enough sɛ wuhunu kɔfɛ bi, nanso wode nnyɛ adwuma. Kɔfɛ no ara wɔde hyɛ wo ma mmerɛ koro, sɛ wɔayɛ no.
Kɛseɛ a ɛwɔ kɛseɛ mu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no nkyerɛkyerɛmu no
GET https://nymbot.ai/api/v1/keys — bɔɔ dwumadie.
| Akwantuo kwan | Twerɛ | Ɛsɛ sɛ wɔde di dwuma | Nkyerɛkyerɛmu |
|---|---|---|---|
include_revoked | boolean (asɛm bi a ɛwɔ mfeɛ mu) | Daabi | Fa kɔm bɔ mmiɛnsa nkyɛn a wɔahyɛ wɔn mu. Default false. |
Aboa mu nkyerɛaseɛ
{ "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);
Kɔm fura mpanimmu kɛseɛ bi wɔtwa
POST https://nymbot.ai/api/v1/keys — bɔɔ nkyerɛwee. Nnuaeɛ 201.
| Akwantuo kwan | Twerɛ | Ɛsɛ sɛ wɔde di dwuma | Nkyerɛkyerɛmu |
|---|---|---|---|
name | ntɛntɛn | Aane | Nkyerɛkyerɛmu 1 kɔsi 40, ɛnyɛ wo deɛ ɛwɔ wo akwan foforɔ mu (sɛ ɛnyɛ nkyerɛkyerɛmu a ɛwɔ hɔ no) (sɛ ɛnyɛ nkyerɛkyerɛmu a ɛyɛ kɛse anaa ketewa no). |
limit_sats | namba a ɛnyɛ nanteɛ namba | Daabi | Sika a wotumi de twaa no wɔ sats mu, ɛkam sɛ ɛnyɛ baako. Ma ɛnyɛ hwee sɛ ɛnyɛ ɛnyɛ kwan a ɛnyɛ hwee. |
reset_period | ntɛntɛn | Daabi | daily, weekly annaa monthly.ɔheneɛ nneɛma limit_satsƐyɛ mmerɛ sɛ ɛbɛtena hɔ ma kɛsetɛ a ɛnyɛ mmerɛ biara. |
expire_at | string anaa integer | Daabi | Berɛ a kɔte no bɛyɛ adwuma ase anka: ISO 8601 bere, anaa millisecond a ɛrekɔ so fi afe 1970 no mu. |
Aboafo (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"
}
}
| Ɛdaeɛ | Ɛberɛ bɛn? |
|---|---|
400 | Din a ɛhia anaa din a ɛyɛ tenten; din a wadi dwumadie ansa na ɛreba (duplicate_name); akannifoɔ a ɛnyɛ namba a ɛnyɛ nkyɛn a ɛnyɛ koraa sɛ baako; asɛm a wɔbɛsɛe no a ɛnyɛ akannifoɔ; awieɛ a ɛdi kan no; asɛm a yɛnni nimdeɛ (unknown_parameter); anaa kwan mmienu a ɛwɔ hɔ a ɛyɛ anadwo (too_many_keys). |
429 | Nkyɛn mmiensa (60) kɛseɛn a saa din yi yɛɛ no, anaa nkyɛn mmienu (120) fi saa kɔmputa dwumadie yi mu, wɔ nnɔnhwere bi mu (rate_limit_exceeded, ne 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);
Akɔnten baako anom nkyerɛkyerɛmu bi a ɛkyerɛ kwan
GET https://nymbot.ai/api/v1/keys/{id} — bɔɔ dwumadie.
Nnuaba a ɛsan no {"data": {…}} ɔde kɔteɛ no, anaa 404
key_not_found Sɛ wo kɛyi biara nni saa ID no a.
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);
Sɛnea wɔsesa nkyɛn bi
PATCH https://nymbot.ai/api/v1/keys/{id} — bɔɔ dwumadie.
Fa biako wɔ biako mu akyiri name, limit_sats, reset_period ne
expire_at, ne kwan a wode yɛ adeɛ bi kɛseɛ no so kwan no so. null εpɛ kwan bi
field: ɛnyɛ kɛseɛ, ɛnyɛ reset, ɛnyɛ ɛda adi. Sɛ wode reset berɛ no si kɔ asofoɔ bi a, ɛhyɛ berɛ foforɔ ase fi zero.
Sɛ wate key bi ase a, woyɛ no asɛm biara (400 key_revoked). Sɛ nea ɛba no
{"data": {…}} ɔde nkyerɛkyerɛmu foforɔ no.
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);
Akae kooko bi tewi
DELETE https://nymbot.ai/api/v1/keys/{id} — bɔɔ dwumadie.
Kyerɛ kwan no ntɛm, ɛketewa. Ɛtena list no mu ne revoked_at hyɛ, na wɔn nso
bɛhu wɔ include_revoked=trueSɛ wotu key a watoom aseɛ no a, n'asɛm no yɛ saa ara. Key ansi a ɛnkɔ so kɛseɛ no nko na wɔhwɛ; nketewa a ɛda ansa no wɔtu wɔn sɛ wotu key foforo bi.
Aboa mu nkyerɛaseɛ
{ "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 nnyinasoɔ mu nnyinasoɔɔ
Hyɛ Lightning wallet bi ne Nostr Wallet Connect ano kókóɛ, na Nymbot bɛkyerɛ mu adeɛ ne ne ho mpaebɔ dɔm wɔ sɛ API dwumadi no bɛyɛ mmerɛ bi a. App no API sheet no wɔ saa nneyɛeɛ yi ara; ɛne endpoints a ɛwɔ ne ase no. Wɔ nyinaa hyɛ aseɛ... asɛm a wɔahyɛ nkyerɛwee wɔ mu.
Sɛnea ɛyɛ: ɛda API kɔkɔɔ a wɔde de to woahyɛɛ sika mu nkyɛmu so a, sɛ nea ɛwɔ saa sika mu no ayɛ kɛseɛ sene wo mpaebo no a, Nymbot yɛ invoice ma woahyɛɛ sika no, kɔpɛ wo wallet sɛ ɛbɛtɔ so, na ɛde credit no hyɛ mu. Ɛhyɛ sika mu mmerɛ biara mma da biara mu mmiɛnsa anadwo mmienu (5 minutes) mma nym biara ne sika mu nkyɛmu biara, enti sɛ kɔkɔɔ pii ba a, ɛbɛtumi ammu wo wallet mu nyinaa. Sika a wode di dwuma wɔ app mu no nnyɛ saa. Berɛ ne sɛnea ɛyɛɛ mmerɛ a wode sika hyɛɛ mu bio no, ne nkyɛmu a ɛhyɛɛ aseɛ no, ne error a ɛhyɛɛ aseɛ no, ɛwɔ settings mu; sɛ sika tɔɔ mu a ɛda error bi a so no, hwɛ ne invoice no wɔ Sika a wɔatow mu asɛm Ɛkyerɛ ɛno ho.
Connection string bi ma obi a ɔwura bi wɔ no tumi ka wo wallet sɛ ɛbɛtodɔ adeɛ. Nymbot
gye no de hyɛ mmoa mu na ɛkɔm hyɛ mu, na ɛde kɛkɛ na ɛtodɔ ne nkwagye mfonini no, nanso
ma connection bi kɛkɛ ma saa adeɛ yi, na ɛwɔ wo wallet mu mfonini a ɛbɛtumi akyɛ, na sɛ ɛbɛtodɔ adeɛ a ɛbɛtumi akyɛ no ne nea woahyɛɛ no kɛkɛ. Wallet no nnye saa adeɛ yi so. pay_invoice.
Sɛnea wɔhyɛ wallet bi nsa so
POST https://nymbot.ai/api/v1/nwc-auto-topup/connect — bɔɔ dwumadie.
| Akwantuo kwan | Twerɛ | Ɛsɛ sɛ wɔde di dwuma | Nkyerɛkyerɛmu |
|---|---|---|---|
nwc_url | ntɛntɛn | Aane | Connection string no, rehyɛ aseɛ nostr+walletconnect://. Nymbot ɛbɛhia wallet no nneɛma sɛ get_info ase sɛ ɔde to mu ansa na ɔde kura no ɛsɛ sɛ ɛyɛ adidi a wɔahyɛ mu. |
threshold_sats | namba a ɛnyɛ nanteɛ namba | Aane | Ma mmoa bere a ne mmoa no bɛnyɛ saa sats yi akyi no. Kom sɛ sats 1,000. |
topup_sats | namba a ɛnyɛ nanteɛ namba | Aane | Ɛde sɛn na ɛsɛ sɛ yɛde hyɛ biara. 1,000 kɔsi 1,000,000 sats. |
tier | ntɛntɛn | Daabi | pro (deɛ ɛda hɔ no) anase standard: akonta a ɛsɛ sɛ whwɛ na wode to so. |
Aboa mu nkyerɛaseɛ
{
"data": {
"connected": true,
"threshold_sats": 5000,
"topup_sats": 20000,
"tier": "pro",
"last_topup_at": null,
"last_topup_sats": null,
"last_error": null
}
}
| Ɛdaeɛ | Ɛberɛ bɛn? |
|---|---|
400 | Ɛnyɛ connection string (invalid_nwc_url); wallet noaanya nni mmuae wɔ ne relay so (nwc_unreachable) anaa asɛe check no (nwc_rejected); kɔnɛktɛn no ntumi nkyɛ invoice no (nwc_missing_permission); anom kyɛn kwan no anaa sika a ɛdi kan no a ɛdi kɛseɛ anaa ɛyɛ kɛseɛ. |
501 | Woatɔ nneɛma de ɛhyɛ mfomsoɔ (automatic top-ups) mu wɔ saa server yi so (nwc_unavailable). Saa ara na ɛfa ɛbia mmienu a ɛdi so no ho. |
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());
Mefiri nkyerɛkyerɛmu no ase reading
GET https://nymbot.ai/api/v1/nwc-auto-topup — bɔɔ dwumadie.
Ɛde adeɛ a ɛfiri connecting no ara na ɛde kɔ, ne sɛ, connected: false na afɔre a ɛbɔ mfeɛ no nso
null sɛ wallet biara nni hɔ a akyerɛkyerɛ mu nnuane biara ntena hɔ. Ɛnyɛ connection string no ara na wɔde ma.
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());
Aka nkyɛn wɔn
DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection — bɔɔ dwumadie.
Ɛsesa connection string a wɔasie no. Wɔnnye mmoa (top-ups) biara bio. Sɛ wopɛ sɛ wopue nea ɛda hɔ no a, wubetumi asɛe connection no wɔ wo wallet mu.
Aboa mu nkyerɛaseɛ
{ "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());
Wosika sika koro koro anaa? Wanhwɛ key biara a.
Wobɛtumi afa nnyigyeɛ a ɔde nnuaeɛ biara nnuaeɛ a ɛnyɛ mmerɛ no so afa Lightning so, wɔ nkyɛdeɛ biara a ɛnni hɔ,
akɔmɔ biara nni hɔ na sika biara nni hɔ: POST /images/generations, POST /images/edits,
POST /videos, POST /audio/speech, POST /audio/transcriptions,
POST /audio/translations ne POST /embeddings. Chat, nsɛm a wɔde bue mu ne
Messages nyinaa hyɛ kɔm (key) nti. Sɛ asɛm bi kɔ so ne kɔm (key) a ɛtena mu a, wɔfa ne nsie (balance) no so bɔ sɛnea ɛyɛ kwan no;
adeɛ no bɔ sɛnea ɛteɛ no hyɛ aseɛ nko ara sɛ kɔm (key) biara nni hɔ a.
Nymbot ka nkyerɛwee mmienu a ɛyɛ adeɛ baako no, fi backend baako: Lightning Labs'
L402 (na wɔataa no wɔ ne din foforɔ no ase, LSAT) ne IETF draft no
Nnyidie HTTP authentication scheme ne saa no lightning ɔnea ne
charge ɔtee. Fa nea wo klientte ase no fa.
Sika bɔn a wode mframa biara nni mu no, ɛyɛ kwan a ɛwɔ no nko ara sɛ API_L402_SECRET ɛwɔ kɔmɔ kɔmɔ nketewa mmiɛnsa ananomi (32) a ɛnyɛ nea ɛwɔ hɔ biara, sɛ hex (akoraa nkyerɛwee 64) anaa base64 (44). Yɛde bi bɛyɛ openssl rand -hex 32.
A nketewa anaa nea wɔbɛtumi ahyia value bi ma ɛde saa ade no si komm na ɛkyerɛw kwan a ɛde maa ɛyɛɛ saa. Sɛ wopɛ sɛ wosenya foforɔ a, fa nea ɛwɔ hɔ no kɔ API_L402_SECRET_PREVIOUS Daako: credentials, status URL ne nnɔbae a wɔayɛ wɔ hɔ ase bɛtena so kɔsi sɛ ɛbɛpa.
Ɔhwɛsɛ no
Ma asɛm no a ɛnni Authorization header. Sɛ ɛyɛ nokware a, biribiara nnye ase, na
wobɛnya 402 Payment Required ɛfiri invoice bi a ɛkyerɛ sɛnea saa asɛmpeɛ no tɔ:
adeyɛ no ara a key bɛtɔ, a wɔahyɛ no sɛ 10 sats wɔ standard credit biara anaa 100 sats wɔ Pro credit biara
na wɔayɛ no kɔ so kɔ sɛ sat kɔtɔ (atɛn sɛnea ɛbɛyɛ a ɛbɛyɛ sat 1, na ɛnyɛ kɔsi 0.05 credit minimum no so). Mmuaeɛ no kura nneɛma mmiɛnsa WWW-Authenticate Nsɛnnennen ma invoice no ara:
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 }
}
Ɔdwom no request parameter no yɛ base64url JSON:
{"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.
Asɛm bi ahyɛ ne ho so wɔ awieeɛ no, kɔ... Content-Type (ne media type na, sɛ ɛyɛ multipart a, ne boundary) na ne SHA-256 a ɛfa ne body bytes a woyɛde too no ho pɛpɛɛpɛ, na ɛbɛtena miniti du ne mmienu (15) mu. Sɛ watae a, tu... teɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛ sɛre bio: ɛno ara
Content-Type na JSON bytes no nso, anaa ɛpono a ɛwɔ multipart mu noho bi
(/images/edits, /audio/transcriptions, /audio/translations)
multipart body a ɛhia no ne boundary a ɛda so no ara. HTTP library pii de boundary foforo kɔtɔ bere biara a wɔrekyerɛ form, enti kyerɛ no ɛkaa na tumi de saa bytes no nnyɛ dua mmienu.
Abantenten biara bɛtumi akyerɛhwɛ asɛm mmiɛnsa wɔ minit bi mu (IPv6 address biara yɛ ne /64 nyinaa).
Akyerɛhwɛ a ne abantenten nte ase nni no, wɔde kɛseɛ kɛseɛ anane mmiɛnsa wɔ minit bi mu, na ɛwom kɛseɛ bi wɔ Nymbot de ma abantenten nyinaa; sɛ wobɛtumi anyɛ asɛm bi ansa na asɛm no afiri mu (te sɛ ne mu ne JSON a ɛnyɛ nokware) a, ɛnyɛ ne de kɔ ade no. Ɛno akyi no, mmuaeɛ no ne 429 ne ho Retry-After, wɔahyɛ no ansa na wɔatumi akenkan nwoma no. Sɛ wɔfrɛ endpoints a wɔantumi nkyerɛ wɔn kwan anaa nea ɛkyerɛ wɔn asɛm no a, ɛregye ne din wɔ nkanhyɛ a ɛwɔ mmerɛ biako mu wɔ adresi biara mu, ɛno yɛ nkan a ɛdidi dwuma mmerɛ 120 wɔ mmerɛ biako mu. Wɔhwɛ nea ɛkyerɛ wɔn asɛm ansa na wɔatumi akenkan nwoma no, na ɛfrɛ nka a Content-Type ɛnyɛ application/json (anɔpa
multipart/form-data adeɛ a wɔde hyɛ mu no yɛato no ano ne 415 na ɔntumi nnya
invoice biara.
Embeddings boɔ nnuaeɛ firi tokens a ɛwɔ mu mu, ne 1.5× nnuaeɛ mu nti, efisɛ ɛdaeɛ nti na yɛhu nokorɛ no, Wopɛ sɛ wopɛ tokens a wɔadi dwuma no nkoaa, na sika a ɛnyɛ dwuma no nso de ba wo nkyɛn sɛ sika nkyɛm nkwatiba.
Merekɔ adeɛ no so
Fa any Lightning wallet to togye invoice no. Wallet no bɛma wo preimage no, ɛyɛ hex characters 64. Afei fa ɛmɔɔ nea ɛyɛ yi biako dwetie:
| Nhyehyɛe | Ti dwumadie |
|---|---|
| L402 | Authorization: L402 <macaroon>:<preimage> (LSAT ɛyɛ nso) |
| Nnyidie | Authorization: Payment <base64url JSON>, ɛhɔ a JSON no wɔ {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}} |
Asɛm a wɔatɔ sika wɔho bɛyɛ ne te sɛ neaa wɔde kɛsɛe yɛɛ no, mmom... nymbot
adeɛ no mu nni muasuo nkyerɛkyerɛmu bi: {"payment": "l402", "tier": "pro", "paid_sats": 237,
"charged_sats": 237}, na nni hɔ X-Nymbot-Balance-Sats header. A
akyerew a wɔdeedee Akwankyerɛ kwan no so no, ɔnya Payment-Receipt header (base64url
JSON ne challenge id no, akɔdeɛ hash no sɛ reference, status ne
timestamp). Awtewɔ aduane a wɔtɔ no nnye nnyina anyɛ nnyina biara ho, enti wɔn nnyɛ wɔn wɔ query history mu.
| Ɛdaeɛ | Ɛberɛ bɛn? |
|---|---|
402 payment_already_used | Ɔbɔdeɛ biara hyɛ adeɛ bi a ɛfata asɛm bi a wɔbɛpa. Ɛdeɛ a ɛba no yɛ nnɔbae foforɔ ma saa asɛm yi, enti ɔtamfo a ɔde ne nneɛma a ɔde hyɛɛ aseɛ no kura (te sɛ lnget ɔno nkoaa na ɔbɔ sɛ ɔbɛhyɛ aseɛ bio. |
402 payment_mismatch | Akwanneɛ deɛ wɔde hyɛɛ deɛ ɛkɔ so bi foforɔ no ho, Content-Type anomɔdeɛ anaa ɔde sika kɔɔ nsuo mu, anaa ɔde sika kɔɔ nsuo mu annye de. Nkwagyeɛ foforɔ bi ba saa asɛm yi ne nti; sɛ sika no yɛɔn kɛseɛ a, nea wode hyɛɛ no de ba ne Ɛ sika nkyɛm nkwatiba (refund_token ne refund_sats wɔ nna mu). |
402 payment_expired | Mfitiɛ minit du ne mmienu (15) a ɛtwam mfiaseɛ challenge no bi. Ahoti foforɔ bi ba ne ho. Sɛ preimage no kyerɛ sɛ woasee a, nea woasee no sɔ kɔ sɛ a sika nkyɛm nkwatiba (refund_token ne refund_sats wɔ mu no), berɛ a; credential no bɛdi mu. |
401 invalid_preimage | Preimage no yi nnyɛ invoice no akwankyerɛ (payment hash) no mu hash no. Akwankyerɛ no nti nni mu nsuo a wɔadi dwuma bi. |
401 invalid_payment_credential | Kyerɛwdeɛ no nkyerɛwee bi wɔ mu, anaa wɔsesa no Nymbot ahyɛɛ aseɛ no akyi, anaa ɛkyerɛ payment hash a Nymbot annye invoice bi adi wɔ ne ho. Macaroon a ɛwɔ caveat a Nymbot nnim, anaa ɛwɔ caveat a ɛyɛ korɔkorɔ, wɔanya no. |
429 rate_limit_exceeded | Nneɛma kɛseɛ sɛ aduonu (30) a wɔanyɛ wɔn adwuma yie ɛfiri saa kwan yi mu wɔ minit bi mu, anaa refund token baako wɔatuma no nnɔn wɔ aduonu (60) kɛseɛ sɛ ɛda wɔ minit bi mu. Te... 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"));
Klient a wɔahyia wɔn so mppx fa Lightning kwan so ma wɔn nkyɛn mpaeɛ no; kyerɛ wɔn kwan a ɛkɔ endpoint no so na ɛgye wɔn adeɛ.
Nvideo
Akyɛdeɛ a wɔatua POST /videos nsɛmmisa 202 Sɛ obi a ɔwɔ kɛyi te sɛ no, ne nea ɛreba bi
status_url: GET ɛnyɛ biara kwan koro a ɛbɛma woatumi asɔ adwuma no. Wɔahyɛ aseɛ
na ɛbɛyɛ nnɔnman hɔ, sɛnea adwuma no bɛtena so bi.
{
"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..."
}
}
Gyina mu refund_token fi saa nkyerɛaseɛ no mu: ɛhɔ nko ara na wɔhunu. Ɛyɛ hɔ aka mpo berɛ a
video no reyɛ adwuma (GET /api/v1/l402/refunds nsɛmmisa "status": "pending");
sɛ render no anni nkyɛaseɛ a wɔanɔ aka bi a, ahwɛdom no mu ahwɛfoɔ de adeɛ no hyɛ ne so. Status URL no kyerɛ
refund_sats adeɛ a wɔatwɛ nsesaeɛ ma adwuma bi nanso wɔannidi token no, enti sɛ wopɛ status URL no a ɛkyerɛ nsesaeɛ no nni hɔ. Sɛ wowɔ token no nso a ɛboa ma adwuma a ɛhyɛɛ aseɛ a obiara ampaeɛ no kɔ tiawa.
Sika a wɔde de hyɛ wo nsa mfeɛ
Sɛ adeɛ a wɔbɔ wo sika no nyɛ yie na nnyimpa no nso de Nymbot sika no fa n'adwuma no ho a, wɔde sika no tena hɔ na
errɔ no nso kyerɛ saa, ne sɛ, charged_sats, sɛnea ɛyɛ sɛ ɛyɛ adeɛ a wɔahyɛ nkyerɛkyerɛmu a ɛwɔ nkyerɛkyerɛmu mu no exactly. Sɛ ɛnyɛ hɔ a wɔatɔ sika no a, mberɛ a ɛyɛ komm no, ɔhaw no wɔ... sika nkyɛm nkwatiba nea wo too sɛn de bɔɔ no nhyira:
{
"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"
}
}
Nneɛma a wɔadi nnyɛ bi de ba kɔ mmara kɔ mu koro te sɛnea ɛyɛɛ no ansa: sɛ wopɛɛ mfonini mmienu na biara nnyɛ no wɔ nnuae a wɔnnyɛ nkyɛdeɛ,
ne nkyerɛkyerɛmu a ɛyɛ adwuma no sɛ nymbot nkitaho no wɔ to mfitiaseɛ mu a ɛpɛ deɛ wɔahyɛ no nkyɛdeɛ nkyɛdeɛ no nti;
transcription a wɔntumi nnkasa ne ne nkyɛn mu mfeɛ ansa na wɔahwɛ no no, wɔbɔ no sɛ ne nkyɛn mu mfeɛ a ɛtɔɔdɔɔ no (ɛnyɛ mfeɛ 30 a ɛtɔɔdɔɔ no), na ɛda bi a ɛbɛyɛ dɛɛ mfeɛ 30 a ɛtɔɔdɔɔ no nkyɛdeɛ nkyɛdeɛ no bɛba; sɛ ɛbɛyɛ sɛ ɛtɔɔdɔɔ mfeɛ 30 a ɛtɔɔdɔɔ no a, wɔbɛrefuse no wɔ 413
na ahwɛadeɛ nyinaa san kɔ. Embeddings de nea nkyerɛkyerɛmu no nanteɛ no san ma. Video a ɛanteɛ ma ne token no san kɔ ne nkyerɛkyerɛmu a ɛsan ma no.
Refund token yɛ random 256-bit code bi. Nymbot ne ne hash nko ara na ɔto so, na ɛma n'ani ɛwɔ nnɔnkɔsa 30 akyi. Ɛwɔ sat balance bi, na wopɛ sɛ woyɛ:
- Fa ɛno to sɛɛ. Tu
Authorization: Bearer REFUND-…wɔ ɛpon nokwaara bi a ɛwɔ ɛhɔ no윗 (OpenAI SDK no deɛ no sɛ ne API key). Agyapadeɛ no fi token no mu na nea ɛtena mu no nea ɛtena wɔ hɔ (refund_token_satswɔ no munymbotɔhunu). Token a ɛho hia yɛ kɛseɛ sene asɛm no mu nnyigyeɛ.402refund_insufficient; nnaadaa a wɔannkyɛ aka no, ɛma sats no san kɔ ɛno ara so token no so. - Hwɛ no.
GET /api/v1/l402/refundsɛde header no ara hyɛ nsa{"sats": 237, "status": "open", "expires_at": "..."}. - Token bi wɔde too no ɛtɔ sɛ mfa anankeso wɔ minit bi mu.
- Fa kɔ nym bi ho. Hyɛ mu kɔ Fa abowura bi di dwuma wɔ
Nymbot app no mu, anaa frɛ
POST /api/v1/l402/refunds/redeemne bi Ɛna asɛm a wɔahyɛ nkyerɛwee wɔ mu ne{"refund_token": "REFUND-...", "balance": "standard"}(anɔpa"pro"). Akonta nyinaa kɔ akonta no mu (sats 10 biara wɔ standard so, 100 wɔ Pro so); sats a ɛnyɛ akonta kɛseɛ ara no tete wɔ token no so ma API requests.
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"
Aboa mu nkyerɛaseɛ
{ "data": { "credited": 23, "tier": "standard", "balance_credits": 123, "remaining_sats": 7 } }