Passer au contenu
Retour à Nymbot

Base de connaissances Développeurs

Chat, messages et réponses

Trois façons de demander quelque chose à un modèle, dans les trois formats que les clients parlent déjà, tous fonctionnant sur les mêmes modèles et facturés de la même manière.

Chat complémentaire

Le format de chat OpenAI, et celui que presque tous les outils prennent en charge. Envoyer la conversation jusqu'ici et recevoir le prochain message.

POST https://nymbot.ai/api/v1/chat/completions Vous avez besoin d’une clé API.

uniquement model et messages Un paramètre d'échantillonnage que le modèle choisi ne prend pas est laissé tomber sans erreur, de sorte qu'un corps de demande fonctionne à travers les modèles. supported_parametersCe qui est refusé plutôt que abandonné est tout ce que le modèle ne peut pas faire du tout: des images pour un modèle qui ne peut pas voir, des outils pour un modèle qui ne peut pas les appeler.

champsTypeNécessaireDescription
modelString àOuinymbot/auto (ou de auto) pour le routage de Nymbot sur le solde standard, ou un modèle de catalogue id tel que anthropic/claude-sonnet-5 sur le bilan Pro. Les noms courts et alias de l'application sont également acceptés. suffisante.
messagesArrayOuiLa conversation, les rôles system, developer (traité comme un système), user, assistant et toolLe contenu est une chaîne ou une liste de text et image_url parties ; images uniquement dans les messages de l'utilisateur. input_audio Les fichiers sont refusés.
streamBouléenNon pasEnvoyez la réponse comme elle est écrite. voir Le streaming.
stream_optionsObjetNon pas{"include_usage": true} ajoute un dernier morceau avec les comptes de jetons et le coût.
max_tokens
max_completion_tokens
IntégraleNon pasLa plupart des jetons à écrire. abaissé au maximum du modèle si plus élevé. Détermine également combien est détenu de votre solde, de sorte qu'un nombre plus petit a besoin de moins de crédit pour commencer.
temperature
top_p
NuméroNon pasContrôle des échantillons : temperature De 0 à 2, top_p De 0 à 1.
stopString ou arrayNon pasTexte qui termine la réponse: une chaîne ou au maximum 4 chaînes, chacune au maximum 256 caractères. nymbot/auto.
seedIntégraleNon pasPour l’échantillonnage répétitif, où le modèle le soutient.
presence_penalty
frequency_penalty
NuméroNon pasContrôles de répétition, chacun de -2 à 2.
response_formatObjetNon pas{"type": "json_object"} ou {"type": "json_schema", "json_schema": {…}}, où le modèle le prend en charge. Non utilisé par nymbot/auto.
tools
tool_choice
parallel_tool_calls
array, chaîne ou objet, booleanNon pasFonction d’appel. voir Les outils d’appel• A web_search L’outil devient Recherche webAu maximum 128 outils et 512 KB de définitions, niché au maximum 64 niveaux de profondeur; plus est un 400.
reasoning_effort
reasoning
String, objetNon pas"minimal", "low", "medium" ou "high"ou {"effort": "high"}. "none" ou {"enabled": false} Il s’éteint. voir Le raisonnement.
pluginsArrayNon pas[{"id": "web", "max_results": 5}] cherche toujours le web en premier. Jusqu'à 10 résultats.
nIntégraleNon pas1 - Tout le reste revient 400.
logit_bias
user
metadata
Objet, String et ObjetNon pasaccepté et non envoyé. logit_bias cartes à un maximum de 300 identifiants de jetons à des nombres de -100 à 100; user Un maximum de 256 caractères metadata possède un maximum de 16 valeurs de chaîne, des clés jusqu'à 64 caractères et des valeurs jusqu'à 512.

La réponse est ordinaire chat.completionAvec le coût de usage.cost (en dollars) et dans les nymbot l’objet . model est le modèle id résolu, donc un nom court revient comme le nom complet. Si le modèle a raisonné avant de répondre, son raisonnement est dans message.reasoning_contentséparée de la réponse.

Réponse

{
  "id": "chatcmpl-5f1c0a9e27d84b3c",
  "object": "chat.completion",
  "created": 1790726400,
  "model": "anthropic/claude-sonnet-5",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "A Lightning invoice is a one-time payment request..."
      },
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 1240,
    "completion_tokens": 380,
    "total_tokens": 1620,
    "prompt_tokens_details": { "cached_tokens": 0 },
    "completion_tokens_details": { "reasoning_tokens": 0 },
    "cost": 0.01895
  },
  "nymbot": {
    "balance": "pro",
    "charged_credits": 0.162,
    "charged_sats": 16.2,
    "balance_credits": 412.425,
    "balance_sats": 41242.5
  }
}

finish_reason est élaboré à partir de ce qui est revenu, car les fournisseurs le rapportent différemment: tool_calls Lorsque le modèle a demandé des outils, length lorsque la réponse a utilisé tous les jetons autorisés (ou que le modèle les a tous raisonnés et n'a pas écrit de réponse), content_filter lorsque le fournisseur a refusé, et stop autrement . usage.completion_tokens_details.reasoning_tokens est toujours 0 : les jetons de raisonnement cachés sont comptés, et facturés, dans completion_tokens.

StatutQuand
400Non pas model ou messages (missing_required_parameter) ; une partie audio ou un fichier, ou des images pour un modèle qui ne peut pas les voir (unsupported_content(plus de 20 photos)too_many_images) ; un paramètre d'échantillonnage du type incorrect ou hors gamme (invalid_value) ; un lien photo qui n'est pas public (invalid_image_url) ; outils sur un modèle qui ne peut pas les appeler (unsupported_tool); n autre que 1 ; a :thinking suffix sur un modèle qui ne peut pas raisonner (model_not_found(ou le fournisseur a refusé la demande)upstream_rejected).
402Le solde que le modèle dépense ne peut pas couvrir la détention.
403Le pire des cas ne correspond pas au cap de la clé (key_limit_reached) plus bas max_tokens Soulever le cap.
404Il n'y a pas de modèle avec ce nom (model_not_found).
429La limite de taux de la clé, ou celle du fournisseur (upstream_rate_limited).
502, 503Le fournisseur a échoué (upstream_error) ou est surchargé (upstream_overloaded, avec Retry-AfterRien n'est facturé à moins que le fournisseur n'ait facturé pour la tentative.

Les codes d'état de chaque action d'endpoint sont répertoriés sous erreurs.

cURL

curl https://nymbot.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5",
    "messages": [
      {"role": "system", "content": "Answer in one short paragraph."},
      {"role": "user", "content": "What is a Lightning invoice?"}
    ],
    "max_tokens": 400
  }'

Python

import os
from openai import OpenAI

client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])

reply = client.chat.completions.create(
    model="anthropic/claude-sonnet-5",
    messages=[
        {"role": "system", "content": "Answer in one short paragraph."},
        {"role": "user", "content": "What is a Lightning invoice?"},
    ],
    max_tokens=400,
)
print(reply.choices[0].message.content)
print(reply.usage.cost)

JavaScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });

const reply = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5",
  messages: [
    { role: "system", content: "Answer in one short paragraph." },
    { role: "user", content: "What is a Lightning invoice?" },
  ],
  max_tokens: 400,
});
console.log(reply.choices[0].message.content);
console.log(reply.usage.cost);

Streaming

avec "stream": true La réponse arrive en tant qu'événement envoyé par le serveur alors que le modèle l'écrit. chat.completion.chunk est a data: ligne, et le flux se termine avec data: [DONE]Le raisonnement entre en delta.reasoning_contentLa réponse dans delta.content.

Faites circuler tout ce qui peut prendre plus de 100 secondes, comme une réponse longue, une grande max_tokens ou un modèle de raisonnement. Une demande qui n'est pas diffusée n'envoie rien jusqu'à ce que la réponse soit complète, et le réseau entre vous et Nymbot peut fermer une connexion vide après environ 100 secondes; le modèle est toujours terminé et ce qu'il a écrit est chargé, mais la réponse est perdue.

Stream

data: {"id":"chatcmpl-5f1c0a9e27d84b3c","object":"chat.completion.chunk","created":1790726400,"model":"anthropic/claude-sonnet-5","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}

data: {"id":"chatcmpl-5f1c0a9e27d84b3c","object":"chat.completion.chunk","created":1790726400,"model":"anthropic/claude-sonnet-5","choices":[{"index":0,"delta":{"content":"A Lightning invoice"},"finish_reason":null}]}

: keep-alive

data: {"id":"chatcmpl-5f1c0a9e27d84b3c","object":"chat.completion.chunk","created":1790726400,"model":"anthropic/claude-sonnet-5","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"chatcmpl-5f1c0a9e27d84b3c","object":"chat.completion.chunk","created":1790726400,"model":"anthropic/claude-sonnet-5","choices":[],"usage":{"prompt_tokens":1240,"completion_tokens":380,"total_tokens":1620,"cost":0.01895},"nymbot":{"balance":"pro","charged_credits":0.162,"charged_sats":16.2,"balance_credits":412.425,"balance_sats":41242.5}}

data: [DONE]
  • Les lignes commençant par : sont des commentaires vivants, envoyés toutes les 15 secondes pendant que le modèle réfléchit.
  • Demandez pour "stream_options": {"include_usage": true} pour obtenir le dernier morceau en haut, avec un vide choices, le token compte, le coût et le nymbot l’objet .
  • Si vous fermez la connexion tôt, le modèle n'est pas arrêté: Nymbot lit le reste du flux du fournisseur, pendant jusqu'à 25 secondes, pour obtenir son comptage de jetons, et vous payez ce que le fournisseur rapporte.
  • Une erreur avant le premier chunk, telle que 401 ou 402, revient comme JSON ordinaire avec son code d'état, pas comme un flux. Une erreur après le début du flux arrive comme un dernier data: {"error": {…}} l'événement, et le flux se termine sans [DONE].
  • Les demandes avec des outils, et les modèles sur le transport des réponses d'OpenAI, ne circulent pas du fournisseur.

cURL

curl -N https://nymbot.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "nymbot/auto",
    "stream": true,
    "stream_options": {"include_usage": true},
    "messages": [{"role": "user", "content": "Write a haiku about sats."}]
  }'

Python

import os
from openai import OpenAI

client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])

stream = client.chat.completions.create(
    model="nymbot/auto",
    stream=True,
    stream_options={"include_usage": True},
    messages=[{"role": "user", "content": "Write a haiku about sats."}],
)
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="", flush=True)
    elif chunk.usage:
        print("\ncost:", chunk.usage.cost)

JavaScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });

const stream = await client.chat.completions.create({
  model: "nymbot/auto",
  stream: true,
  stream_options: { include_usage: true },
  messages: [{ role: "user", content: "Write a haiku about sats." }],
});
for await (const chunk of stream) {
  if (chunk.choices.length) process.stdout.write(chunk.choices[0].delta.content || "");
  else if (chunk.usage) console.log("\ncost:", chunk.usage.cost);
}

outil d'appel

Décrivez les fonctions dans tools et le modèle peut demander à l'un d'eux d'être appelé au lieu de répondre. Vous exécutez la fonction, ajoutez son résultat comme un tool Un message avec le même tool_call_idNymbot n'exécute jamais vos fonctions ; il transmet la demande du modèle à vous.

tool_choice prend "auto", "none", "required" ou {"type": "function", "function": {"name": "…"}}La liste des modèles indique quels modèles peuvent appeler des outils (capabilities.toolsLes outils sont refusés 400 unsupported_tool est nymbot/auto et sur les quelques modèles de catalogue qui fonctionnent sur le transport Responses d'OpenAI, auxquels Nymbot ne peut pas passer des outils.

avec "stream": true, une requête avec des outils s'exécute en une seule pièce et est ensuite envoyée comme une séquence normale: le rôle, un morceau portant chaque appel à outil avec son index, son id, son nom et ses arguments, et le morceau de fin.

La réponse, en partie

"choices": [
  {
    "index": 0,
    "message": {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_7d2e",
          "type": "function",
          "function": { "name": "get_invoice_status", "arguments": "{\"invoice_id\":\"a41f\"}" }
        }
      ]
    },
    "finish_reason": "tool_calls"
  }
]

cURL

curl https://nymbot.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5",
    "messages": [{"role": "user", "content": "Has invoice a41f been paid?"}],
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_invoice_status",
        "description": "Look up whether an invoice is paid.",
        "parameters": {
          "type": "object",
          "properties": {"invoice_id": {"type": "string"}},
          "required": ["invoice_id"]
        }
      }
    }]
  }'

Python

import json, os
from openai import OpenAI

client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])

tools = [{
    "type": "function",
    "function": {
        "name": "get_invoice_status",
        "description": "Look up whether an invoice is paid.",
        "parameters": {
            "type": "object",
            "properties": {"invoice_id": {"type": "string"}},
            "required": ["invoice_id"],
        },
    },
}]
messages = [{"role": "user", "content": "Has invoice a41f been paid?"}]

reply = client.chat.completions.create(model="anthropic/claude-sonnet-5", messages=messages, tools=tools)
call = reply.choices[0].message.tool_calls[0]
args = json.loads(call.function.arguments)

messages.append(reply.choices[0].message)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps({"paid": True})})

final = client.chat.completions.create(model="anthropic/claude-sonnet-5", messages=messages, tools=tools)
print(final.choices[0].message.content)

JavaScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });

const tools = [{
  type: "function",
  function: {
    name: "get_invoice_status",
    description: "Look up whether an invoice is paid.",
    parameters: {
      type: "object",
      properties: { invoice_id: { type: "string" } },
      required: ["invoice_id"],
    },
  },
}];
const messages = [{ role: "user", content: "Has invoice a41f been paid?" }];

const reply = await client.chat.completions.create({ model: "anthropic/claude-sonnet-5", messages, tools });
const call = reply.choices[0].message.tool_calls[0];
const args = JSON.parse(call.function.arguments);

messages.push(reply.choices[0].message);
messages.push({ role: "tool", tool_call_id: call.id, content: JSON.stringify({ paid: true }) });

const final = await client.chat.completions.create({ model: "anthropic/claude-sonnet-5", messages, tools });
console.log(final.choices[0].message.content);

Images dans une demande

Modèles avec capabilities.vision Peut lire des images.Ajouter un image_url partie à un message utilisateur, avec un public https:// Lien ou A data:image/…;base64, URL. Jusqu'à 20 images par demande. images SVG sont refusées, et ainsi est un lien de plus de 4 096 caractères ou un avec un nom d'utilisateur ou un mot de passe dans celui-ci (400 invalid_image_urlUne option detail est auto, low ou high.

avec nymbot/auto, une demande avec une image en elle est redirigée vers un modèle standard qui peut voir. capabilities.vision Refuser les photos avec 400 unsupported_contentUn lien doit pointer vers un hôte public; Nymbot transmet l'image au fournisseur du modèle et ne la conserve pas.

Une image est facturée comme les jetons d'entrée que le fournisseur compte pour elle, comme le reste de la demande.

cURL

curl https://nymbot.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "What is in this picture?"},
        {"type": "image_url", "image_url": {"url": "https://example.com/receipt.jpg"}}
      ]
    }]
  }'

Python

import base64, os
from openai import OpenAI

client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])

with open("receipt.jpg", "rb") as f:
    data_url = "data:image/jpeg;base64," + base64.b64encode(f.read()).decode()

reply = client.chat.completions.create(
    model="anthropic/claude-sonnet-5",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What is in this picture?"},
            {"type": "image_url", "image_url": {"url": data_url}},
        ],
    }],
)
print(reply.choices[0].message.content)

JavaScript

import { readFile } from "node:fs/promises";
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });

const dataUrl = "data:image/jpeg;base64," + (await readFile("receipt.jpg")).toString("base64");

const reply = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5",
  messages: [{
    role: "user",
    content: [
      { type: "text", text: "What is in this picture?" },
      { type: "image_url", image_url: { url: dataUrl } },
    ],
  }],
});
console.log(reply.choices[0].message.content);

Le raisonnement

Modèles avec capabilities.reasoning peut réfléchir avant qu'ils ne répondent. demande plus ou moins avec reasoning_effort ("minimal", "low", "medium" ou "high") ou "reasoning": {"effort": "high"}ou ajouter :thinking au nom du modèle, ce qui signifie un effort élevé. Sur un modèle sans raisonnement, le paramètre est ignoré. nymbot/auto, :thinking Envoie la demande à l'itinéraire de raisonnement standard.

Sur les modèles Anthropic, l’effort devient un budget de réflexion d’environ 1 000, 2 000, 8 000 ou 16 000 jetons, jamais plus que max_tokens La pensée est laissée de côté quand tool_choice force un outil, et lorsque la demande continue une boucle d'outils (son dernier message est un résultat d'outil), parce que Anthropic a besoin de la pensée précédemment signée pour la reprendre.

Le raisonnement revient en message.reasoning_contentou delta.reasoning_content lors du streaming, jamais mélangé dans la réponse. Le raisonnement est la sortie et est chargé en tant que tel, à l'intérieur completion_tokensCertains fournisseurs ne retournent pas du tout le texte de raisonnement, et il est toujours facturé.

cURL

curl https://nymbot.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5",
    "reasoning_effort": "high",
    "messages": [{"role": "user", "content": "Is 2^61 - 1 prime? Show why."}]
  }'

Python

import os
from openai import OpenAI

client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])

reply = client.chat.completions.create(
    model="anthropic/claude-sonnet-5",
    reasoning_effort="high",
    messages=[{"role": "user", "content": "Is 2^61 - 1 prime? Show why."}],
)
message = reply.choices[0].message
print(getattr(message, "reasoning_content", None))
print(message.content)

JavaScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });

const reply = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5",
  reasoning_effort: "high",
  messages: [{ role: "user", content: "Is 2^61 - 1 prime? Show why." }],
});
console.log(reply.choices[0].message.reasoning_content);
console.log(reply.choices[0].message.content);

Modèle de suffixes

Un suffix sur le nom du modèle change la façon dont la demande est traitée, sans un autre champ. Ils fonctionnent sur les ids complets et les noms courts de la même manière, comme dans anthropic/claude-sonnet-5:online.

suffisantEffet
:onlineRecherche d'abord sur le web, comme plugins: [{"id": "web"}]Voir Recherche web.
:thinkingUn grand effort de raisonnement ; sur nymbot/autosur un modèle qui ne peut pas raisonner, 400 model_not_found avec “no endpoints found”.
:nitro, :floor, :exacto, :extendedChaque modèle de catalogue a un itinéraire, de sorte qu'il n'y a pas de plus rapide, moins cher ou plus long à choisir; les suffixes sont autorisées de sorte que les noms de modèle copiés d'autres services fonctionnent toujours.

Tout autre suffixe est ignoré. Le nom entier est essayé en premier, de sorte qu'un modèle dont l'identifiant contient vraiment un colon fonctionne toujours; en l'absence de cela, les suffixes sont retirées de la fin une à la fois jusqu'à ce qu'un modèle correspond. Un nom de modèle peut être au maximum 200 caractères long avec au maximum 4 suffixes; un plus long est refusé avec 400 invalid_value.

cURL

curl https://nymbot.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5:thinking",
    "messages": [{"role": "user", "content": "Plan a three-day trip to Lisbon."}]
  }'

Python

import os
from openai import OpenAI

client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])

reply = client.chat.completions.create(
    model="anthropic/claude-sonnet-5:thinking",
    messages=[{"role": "user", "content": "Plan a three-day trip to Lisbon."}],
)
print(reply.choices[0].message.content)

JavaScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });

const reply = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5:thinking",
  messages: [{ role: "user", content: "Plan a three-day trip to Lisbon." }],
});
console.log(reply.choices[0].message.content);

Nymbot recherche le dernier message de l'utilisateur (ses 2 000 premiers caractères), lit les meilleures pages et les donne au modèle avec la question, marquée comme contenu extérieur dont le modèle ne devrait pas prendre des instructions.

  • Toujours chercher: "plugins": [{"id": "web", "max_results": 5}]ou a :online suffix sur le modèle.
  • Rechercher quand ça aide: "tools": [{"type": "web_search", "parameters": {"max_results": 5}}]Il est également accepté comme web_search_preview ou openrouter:web_searchNymbot recherche seulement lorsque la question semble avoir besoin d'informations actuelles, le même test que l'application utilise.

max_results est 5 par défaut et au maximum 10. les sources reviennent dans nymbot.web_search.sourcesChacun avec une title, snippet et urlEt comme url_citation Notes sur le message.

Chaque recherche qui fonctionne coûte 0,008 $, convertie en sats, au-dessus des jetons, et cela fait partie du hold.Les pages qu'il lit sont aussi des jetons d'entrée, donc une réponse du web coûte plus cher que la même question posée froidement, parfois plusieurs fois plus.

La réponse, en partie

"nymbot": {
  "balance": "pro",
  "charged_credits": 0.431,
  "charged_sats": 43.1,
  "balance_credits": 411.994,
  "balance_sats": 41199.4,
  "web_search": {
    "sources": [
      { "title": "Lightning Network - Wikipedia", "snippet": "The Lightning Network is a payment protocol...", "url": "https://en.wikipedia.org/wiki/Lightning_Network" }
    ]
  }
}

cURL

curl https://nymbot.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5",
    "plugins": [{"id": "web", "max_results": 5}],
    "messages": [{"role": "user", "content": "What changed in the latest Bitcoin Core release?"}]
  }'

Python

import os
from openai import OpenAI

client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])

reply = client.chat.completions.create(
    model="anthropic/claude-sonnet-5",
    messages=[{"role": "user", "content": "What changed in the latest Bitcoin Core release?"}],
    extra_body={"plugins": [{"id": "web", "max_results": 5}]},
)
print(reply.choices[0].message.content)
for source in reply.model_extra["nymbot"]["web_search"]["sources"]:
    print(source["url"])

JavaScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });

const reply = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5",
  plugins: [{ id: "web", max_results: 5 }],
  messages: [{ role: "user", content: "What changed in the latest Bitcoin Core release?" }],
});
console.log(reply.choices[0].message.content);
for (const source of reply.nymbot.web_search.sources) console.log(source.url);

Réponse à API

Le format plus récent d'OpenAI, utilisé par l'OpenAI Agents SDK et par Codex. Il fonctionne sur les mêmes modèles, facturation et fonctionnalités que Chat Completions.

POST https://nymbot.ai/api/v1/responses Vous avez besoin d’une clé API.

champsTypeNécessaireDescription
modelString àOuicomme pour Chat complémentaireLes suffixes sont inclus.
inputString ou arrayOuiUne chaîne, ou une liste d’éléments : messages (rôles) user, assistant, system, developer) avec input_text, input_image et output_text des parties, et function_call et function_call_output Articles pour outils. input_image Prenez un image_url Un lien ou une URL de données, pas un identifiant de fichier reasoning et web_search_call Les objets sont déchirés ; item_reference est refusée .
instructionsString àNon pasInstructions du système.
max_output_tokensIntégraleNon pasLe plus gros morceau à écrire.
temperature
top_p
NuméroNon pasContrôles d'échantillonnage, où le modèle les prend.
tools
tool_choice
parallel_tool_calls
array, chaîne ou objet, booleanNon pasLes outils de fonctionnement, dans la forme des réponses ({"type": "function", "name": …, "parameters": …}) A web_search ou web_search_preview L’outil devient Recherche web Lorsque cela aide, d'autres outils intégrés sont refusés.
reasoningObjetNon pas{"effort": "minimal" | "low" | "medium" | "high"}. xhigh et max signifie high; none Tourne le dessus.
text.format
response_format
ObjetNon pasUne sortie structurée, comme un schéma JSON ou json_object.
metadataObjetNon pasRetourné inchangé dans la réponse. Pour un maximum de 16 valeurs de chaîne, des clés jusqu'à 64 caractères et des valeurs jusqu'à 512.
streamBouléenNon pasÉvénements de streaming comme décrit ci-dessous.
storeBouléenNon pasRien n'est stocké, et la réponse dit toujours "store": false.
previous_response_id
conversation
background
String, Objet et BooleanNon pasNon soutenu : 400 unsupported_parameterLes réponses ne sont pas enregistrées, alors envoyez toute la conversation dans input à chaque fois.

Réponse

{
  "id": "resp_8c1e4b0f9a2d4e61",
  "object": "response",
  "created_at": 1790726400,
  "status": "completed",
  "model": "anthropic/claude-sonnet-5",
  "output": [
    {
      "type": "message",
      "id": "msg_2b7f",
      "role": "assistant",
      "status": "completed",
      "content": [{ "type": "output_text", "text": "A Lightning invoice is...", "annotations": [] }]
    }
  ],
  "output_text": "A Lightning invoice is...",
  "usage": {
    "input_tokens": 1240,
    "input_tokens_details": { "cached_tokens": 0 },
    "output_tokens": 380,
    "output_tokens_details": { "reasoning_tokens": 0 },
    "total_tokens": 1620
  },
  "incomplete_details": null,
  "error": null,
  "instructions": null,
  "store": false,
  "previous_response_id": null,
  "metadata": {},
  "nymbot": { "balance": "pro", "charged_credits": 0.162, "charged_sats": 16.2, "balance_credits": 412.425, "balance_sats": 41242.5 }
}

Une requête d'outil apparaît dans output comme a function_call Point avec call_id, name et argumentsEnvoyer le résultat comme a function_call_output Un article avec le même call_idLe raisonnement, quand le modèle le renvoie, est un reasoning Point avec reasoning_text Contenu enregistré en premier. status est incomplete Quand la réponse frappe max_output_tokens Le vendeur a refusé, avec incomplete_details.reason Mise à max_output_tokens ou content_filterLa réponse échoit également les paramètres de la demande (température, outils, choix d'outils, etc.) comme le fait OpenAI, et porte le nymbot coût de l’objet.

En streaming, chaque événement est un event: ligne et a data: Ligne avec A sequence_numberDans cet ordre : response.created, response.in_progress, response.output_item.added, response.content_part.addedN’importe quel nombre de response.output_text.delta, response.output_text.done, response.content_part.done, response.output_item.doneEt enfin response.completed avec l'usage et le coût. Une réponse court avec response.incomplete au lieu de cela, et un échec après que le flux a commencé avec response.failedRésoudre les flux comme son propre objet avec response.reasoning_text.delta et .doneLes appels d'outils viennent après le message, chacun en tant qu'élément avec response.function_call_arguments.delta et .done.

StatutQuand
400Non pas model ou input; previous_response_id, conversation, background ou un item_reference (unsupported_parameterUn outil ou un type de contenu non pris en charge.
402, 403, 404, 429, 502, 503Pour les compléments de chat.

cURL

curl https://nymbot.ai/api/v1/responses \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5",
    "instructions": "Answer in one short paragraph.",
    "input": "What is a Lightning invoice?"
  }'

Python

import os
from openai import OpenAI

client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])

response = client.responses.create(
    model="anthropic/claude-sonnet-5",
    instructions="Answer in one short paragraph.",
    input="What is a Lightning invoice?",
)
print(response.output_text)

JavaScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });

const response = await client.responses.create({
  model: "anthropic/claude-sonnet-5",
  instructions: "Answer in one short paragraph.",
  input: "What is a Lightning invoice?",
});
console.log(response.output_text);

Messages anthropologiques

Le format Anthropic, pour les SDK Anthropic et Claude Code. Il fonctionne avec tous les modèles du catalogue, pas seulement Claude : la demande est traduite, exécutée par le même pipeline, et traduite en arrière.

POST https://nymbot.ai/api/v1/messages Vous avez besoin d'une clé API, comme x-api-key ou Authorization: Bearer.

Le anthropic-version et anthropic-beta Les noms de modèles anthropes sont associés au catalogue, de sorte que Claude Code et les SDKs fonctionnent avec les noms qu’ils utilisent déjà :

  • Un nom que le catalogue connaît, comme claude-sonnet-5 ou anthropic/claude-opus-5Il est utilisé comme il est.
  • Une autre date (-20260514), -latestUne version telle que -v1Un bracelet comme [1m] et un anthropic/ ou anthropic. les préfixes sont supprimés, et les points et les dashes dans la version sont essayés dans les deux sens (claude-haiku-4-5 Trouver claude-haiku-4.5).
  • Si cela ne correspond toujours pas, la famille (Opus, Sonnet ou Haiku) est utilisée, tant que la version du catalogue est la même ou plus récente que celle demandée.
  • Un nom qui ne correspond à rien revient 404 not_found_error.
champsTypeNécessaireDescription
modelString àOuiUn nom de modèle de catalogue ou un nom de modèle anthropologique.
max_tokensIntégraleOuiLe plus gros morceau à écrire.
messagesArrayOuiuser et assistant tourne, avec text, image (base64 ou source URL) tool_use et tool_result des blocs. thinking Les blocs des tours précédents sont acceptés et jetés.
systemString ou arrayNon pasSystème prompt, comme une chaîne ou des blocs de texte.
temperature
top_p
NuméroNon pasContrôles d'échantillonnage, où le modèle les prend. top_k Il est accepté et abandonné.
stop_sequencesRésumé de StringsNon pasTexte qui termine la réponse. Au maximum 4 chaînes, chacune au maximum 256 caractères.
tools
tool_choice
Array, objetNon pasDes outils avec name, description et input_schema• A web_search L’outil de serveur s’affiche Recherche webLes autres outils intégrés d'Anthropic (bash, éditeur de texte, utilisation informatique) sont refusés avec unsupported_tool. tool_choice prend auto, any, tool ou noneet disable_parallel_tool_use.
thinkingObjetNon pas{"type": "enabled", "budget_tokens": 8192}, {"type": "adaptive"} ou {"type": "disabled"}Le budget choisit un niveau d’effort : en dessous de 2 048 minimum, de 2 048 bas, de 8 192 moyen, de 16 384 haut. output_config.effortOu très haut.
streamBouléenNon pasStream dans le format d'événement d'Anthropic.
metadataObjetNon pasAccepté et ignoré.

Réponse

{
  "id": "msg_01c7a2f93e5b4d08",
  "type": "message",
  "role": "assistant",
  "model": "anthropic/claude-sonnet-5",
  "content": [{ "type": "text", "text": "A Lightning invoice is..." }],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 1240,
    "output_tokens": 380,
    "cache_read_input_tokens": 0,
    "cache_creation_input_tokens": 0
  },
  "nymbot": { "balance": "pro", "charged_credits": 0.162, "charged_sats": 16.2, "balance_credits": 412.425, "balance_sats": 41242.5 }
}

content On peut aussi tenir tool_use blocs et a thinking Le bloc, dont signature Il est vide. stop_reason est end_turn, max_tokens, tool_use ou refusalIl a travaillé de la même manière que finish_reason est Chat complémentaire; stop_sequence est toujours null, même quand une séquence d'arrêt a terminé la réponse. input_tokens ne compte que les entrées fraîches ; les entrées en cache sont dans les deux champs de cache. nymbot Objet et le X-Nymbot-Cost-Sats du header.

Streamed, les événements sont Anthropic's : message_start, content_block_start, ping, content_block_delta (text_delta, input_json_delta ou thinking_delta), content_block_stop, message_delta avec la raison d’arrêt, l’usage et le nymbot coût de l’objet, et message_stop• A ping est également envoyé toutes les 15 secondes pendant que le modèle fonctionne. Les appels à outils arrivent après le texte, chacun en tant que tool_use bloc avec toute son entrée dans un input_json_delta.

Erreurs sur cet endpoint utilisent le format d'Anthropic: {"type": "error", "error": {"type": "not_found_error", "message": "…"}}Un court équilibre est 402 billing_errorUn fournisseur surchargé 503 overloaded_errorUne défaillance après le début du flux est envoyée comme un error événement .

cURL

curl https://nymbot.ai/api/v1/messages \
  -H "x-api-key: $NYMBOT_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "What is a Lightning invoice?"}]
  }'

Python

import os
import anthropic

client = anthropic.Anthropic(base_url="https://nymbot.ai/api", api_key=os.environ["NYMBOT_API_KEY"])

message = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "What is a Lightning invoice?"}],
)
print(message.content[0].text)

JavaScript

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({ baseURL: "https://nymbot.ai/api", apiKey: process.env.NYMBOT_API_KEY });

const message = await client.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "What is a Lightning invoice?" }],
});
console.log(message.content[0].text);

Compter les tokens

Une estimation du nombre de jetons d'entrée qu'une demande Messages utiliserait, afin qu'un client puisse vérifier avant d'envoyer.

POST https://nymbot.ai/api/v1/messages/count_tokens Vous avez besoin d’une clé API.

Le corps est le même que le Messageset sans max_tokens; le nom du modèle doit résoudre. Le comptage est une estimation: les caractères de la prompt du système, les messages, les appels à outils et les définitions d'outils divisés par quatre, plus 1 600 pour chaque image. Ce n'est pas le tokenizer propre du fournisseur, de sorte que le compte réel peut différer.

Réponse

{ "input_tokens": 318 }

cURL

curl https://nymbot.ai/api/v1/messages/count_tokens \
  -H "x-api-key: $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "messages": [{"role": "user", "content": "What is a Lightning invoice?"}]
  }'

Python

import os
import anthropic

client = anthropic.Anthropic(base_url="https://nymbot.ai/api", api_key=os.environ["NYMBOT_API_KEY"])

count = client.messages.count_tokens(
    model="claude-sonnet-5",
    messages=[{"role": "user", "content": "What is a Lightning invoice?"}],
)
print(count.input_tokens)

JavaScript

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({ baseURL: "https://nymbot.ai/api", apiKey: process.env.NYMBOT_API_KEY });

const count = await client.messages.countTokens({
  model: "claude-sonnet-5",
  messages: [{ role: "user", content: "What is a Lightning invoice?" }],
});
console.log(count.input_tokens);

Liste des modèles

Chaque modèle et générateur de l'API accepte, avec ce qu'il coûte.La liste est lue du même catalogue en direct que le sélectionneur de l'application, donc c'est toujours ce que le serveur exécutera.

GET https://nymbot.ai/api/v1/models Aucune clé n'est nécessaire. Caché pendant cinq minutes.

GET /api/v1/models/{id} Retourner une entrée.

champsTypeNécessaireDescription
typeString (recherche)Non paschat (Le défaut est image, video, audio, embedding ou allPlusieurs d’entre elles peuvent être utilisées, comme image,video.

Les prix sont ce que vous payez, avec la redevance et la marge déjà en, en dollars et en taux au prix Bitcoin actuel. balance indique le montant que dépense le modèle. nymbot_key est le nom court du modèle dans l'application. created est toujours 0, car le catalogue n'enregistre pas le moment où un modèle a été ajouté. per_request plutôt.

nymbot/auto est toujours le premier, prix comme variable, avec une routes Liste donnant les tarifs de chaque itinéraire standard. Il liste la vision et le raisonnement, mais pas les outils.

GET /api/v1/models/{id} accepte les mêmes noms et alias en tant que demande, et renvoie l'entrée pour le modèle auquel ils se résolvent.

Réponse

{
  "object": "list",
  "data": [
    {
      "id": "anthropic/claude-sonnet-5",
      "object": "model",
      "type": "chat",
      "owned_by": "anthropic",
      "name": "Claude Sonnet 5",
      "created": 0,
      "context_length": 1000000,
      "max_output_tokens": 64000,
      "architecture": { "input_modalities": ["text", "image"], "output_modalities": ["text"] },
      "supported_parameters": ["max_tokens", "temperature", "tools", "tool_choice", "reasoning", "response_format", "stop"],
      "capabilities": { "vision": true, "video": false, "tools": true, "reasoning": true, "web_search": true },
      "balance": "pro",
      "pricing": {
        "type": "per_token",
        "currency": "USD",
        "input_per_1M_tokens": 4.725,
        "output_per_1M_tokens": 23.625,
        "cache_read_per_1M_tokens": 0.4725,
        "sats_input_per_1M_tokens": 4038,
        "sats_output_per_1M_tokens": 20192
      },
      "description": "...",
      "nymbot_key": "claude-sonnet"
    }
  ]
}

Les autres types :

  • Imagerie Les entrées ont capabilities (accepts_image_url, requires_image_url, edit(et un prix per_generation.
  • Vidéo Les entrées ont max_duration_seconds et resolutionset un prix per_second pour chaque résolution.
  • Audio Les entrées ont audio_type speech ou transcriptionLe prix per_1k_chars ou per_minute.
  • Intégration Les entrées ont dimensions, context_length, max_inputs et un prix par million de jetons d'entrée.

Prix marqués "estimated": true est l'estimation de l'application pour un générateur dont le prix n'est pas publié. type retournés 400.

cURL

curl "https://nymbot.ai/api/v1/models?type=chat"

Python

import requests

models = requests.get("https://nymbot.ai/api/v1/models", params={"type": "chat"}).json()["data"]
for m in models:
    print(m["id"], m["balance"], m["pricing"].get("input_per_1M_tokens"))

JavaScript

const res = await fetch("https://nymbot.ai/api/v1/models?type=chat");
const { data } = await res.json();
for (const m of data) console.log(m.id, m.balance, m.pricing.input_per_1M_tokens);