NULLMOTH / FIELD MANUAL

Your first request.

One endpoint. Your own tools. Start with a small output budget.

We run Recon ourselves on a rented GPU instance. Your requests go directly to the model we operate, rather than a third-party model API. Inference runs on our server, not on your device.

Quick start

Open your account, connect your Ethereum wallet and receive $1 in trial credit once per new account. Create an API key, then replace YOUR_API_KEY in an example below. Signing in does not send a transaction.

Base URL
https://nullmoth.com/v1
Model ID
nullmoth-recon
Protocol
OpenAI-compatible Chat Completions

For compatible clients, use the Base URL above without adding /chat/completions. The examples below use the complete request URL. Your account needs available credit; creating a key does not add credit.

First request · Bash / Git Bash
export NULLMOTH_API_KEY="YOUR_API_KEY"

curl --fail-with-body "https://nullmoth.com/v1/chat/completions" \
  -H "Authorization: Bearer $NULLMOTH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"nullmoth-recon","messages":[{"role":"user","content":"Reply with one word: ready"}],"max_tokens":64,"stream":false}'
Windows · PowerShell
First request · PowerShell
$env:NULLMOTH_API_KEY = 'YOUR_API_KEY'
$requestBody = @{
  model = 'nullmoth-recon'
  messages = @(@{ role = 'user'; content = 'Reply with one word: ready' })
  max_tokens = 64
  stream = $false
} | ConvertTo-Json -Depth 5

$response = Invoke-RestMethod `
  -Uri 'https://nullmoth.com/v1/chat/completions' `
  -Method Post `
  -ContentType 'application/json; charset=utf-8' `
  -Headers @{ Authorization = "Bearer $env:NULLMOTH_API_KEY" } `
  -Body ([System.Text.Encoding]::UTF8.GetBytes($requestBody))
$response.choices[0].message.content

A successful call returns the answer in choices[0].message.content and token counts in usage. Keep your key private. A 401 means the key is missing or invalid; a 402 means the available credit cannot cover the request.

Stream the response

Streaming · Bash / Git Bash
export NULLMOTH_API_KEY="YOUR_API_KEY"

curl --no-buffer --fail-with-body "https://nullmoth.com/v1/chat/completions" \
  -H "Authorization: Bearer $NULLMOTH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"nullmoth-recon","messages":[{"role":"user","content":"Explain broken access control in two sentences."}],"max_tokens":256,"stream":true,"stream_options":{"include_usage":true}}'

Read choices[0].delta.content from SSE events. Usage-only events have an empty choices array. Wait for [DONE] and handle HTTP or stream errors; HTTP 200 alone does not confirm a completed response.

All examples call the hosted API. They do not require a local model server. Thinking, tools and limits are documented below.

Keep your key server-side.

Use Authorization: Bearer YOUR_KEY. Keys are shown once, when created. You can create up to five active keys and revoke them in your account. Never publish a key in browser code, a repository or a URL. Chat uses a session cookie, not your API key.

Wallet sign-in uses a single-use, five-minute challenge bound to this browser and domain. Ethereum Mainnet EOA wallets are supported; smart-contract wallets and WalletConnect are not supported yet. The API still uses your API key, so scripts do not need to sign every request.

What works today

Current backend capabilities
Feature Status
Chat completions JSON and SSE streaming, cancellation and verified usage.
Model nullmoth-recon — NullMoth Recon, Qwen3.8 fine-tuned for cybersecurity and red-team workflows. Base variant: OrcaRouter’s Qwen3.8-27B Uncensored NVFP4. Legacy requests using atelier-large remain supported.
Limits 131,072 characters per message, 524,288 total, 400 messages, 16,384 output tokens by default.
Tool calls / vision Tool schemas and tool_choice are supported for agent clients: the model returns structured tool_calls (streamed as a single synthesized chunk sequence) and tool results are accepted as tool messages. Vision is not exposed by this backend.
Long context The model configuration can exceed these limits; that is not the public API allowance.

Output budgets are capped at 16,384 tokens and reduced to fit the remaining 98,304-token context. Messages are never silently removed. If the input itself fills the context, shorten or summarize it. Tool names, forced choices and arguments are validated. Supported tool schemas include types, properties, required, items, additionalProperties, enum, const, numeric bounds, length bounds and anyOf/oneOf/allOf. References, patterns and formats are not supported; schemas are limited to 1,000 nodes, depth 12 and 128 KiB combined. Tool streams send keepalive comments while waiting for the complete validated result.

Structured outputs accept response_format types text, json_object and json_schema. JSON schemas use the same restricted subset, with a 32 KiB envelope. Length and item bounds cannot exceed 16,384. Request bodies must arrive within 5 seconds; generation has a separate deadline. Account changes are limited to 60 per minute; signing out and revoking keys remain available.

Handle errors explicitly.

Check HTTP status before reading the response. Preserve user input and offer a retry, with backoff.

HTTP Action
400 Fix the request parameters.
401 / 403 Check authentication and origin.
402 Add credit or lower the output budget.
408 Send the complete request body within 5 seconds.
429 Wait for Retry-After before retrying.
500 / 502 / 503 / 504 Report unavailability. Avoid retry loops.

Pay for measured usage.

Provisional rates: $0.39 per million input tokens and $2.50 per million output tokens. Before generation, Qwen tokenizes the input and the server reserves its cost plus the maximum output budget. A temporary input margin covers tokenizer differences: the larger of 64 tokens or half the estimated input. Valid final usage determines the charge; unused credit is released. Closing a stream does not cancel billing: the reserved budget remains held until the engine finishes. Valid final token counts are charged within that budget. Interrupted streams are charged for validated intermediate usage. If streamed output lacks reliable counts, credit remains reserved for usage verification. Contact support if a reservation remains pending.

Usage separates input and output tokens. When the engine reports reasoning tokens, they are included in output, never charged a second time. An absent reasoning breakdown means unavailable, not zero. Thinking is off by default; set thinking to true or reasoning_effort to medium/high to enable it.

OpenAI Chat Completions compatibility

Use /v1/chat/completions. Recon supports text messages, text content arrays, leading developer/system instructions, JSON and SSE, function tools and bounded structured outputs. Responses API, images, audio and legacy functions/function_call are not supported.

max_completion_tokens is an alias for max_tokens (a positive integer upper bound, including reasoning). If both are supplied, they must agree. Sampling accepts top_p (greater than 0, at most 1), frequency_penalty and presence_penalty (-2–2), seed (0–4,294,967,295) and stop (1–4 non-empty strings, at most 1,024 characters each). Seed does not guarantee identical output.

Oversized positive budgets are capped instead of rejected. Response headers X-NullMoth-Max-Tokens and X-NullMoth-Reasoning-Effort report the effective output cap and reasoning mode. The default output cap remains 16,384 tokens.

parallel_tool_calls: false limits each response to one validated tool call. Only n: 1, logprobs: false, top_logprobs: 0, empty logit_bias, store: false and modalities: ["text"] are supported. store: false does not disable operational or debug logging. user, safety_identifier and metadata are accepted as compatibility metadata but are not used for model input, retrieval or identity checks.

Validation errors return error.code, error.message, error.type and error.param. Unsupported fields are rejected explicitly; remove the indicated field or use a supported value. A missing param means the error is not tied to a specific parameter.

Thinking mode

Set thinking or reasoning_effort on each request. Accepted efforts are none, medium and high. Explicit thinking: false takes precedence over medium/high. thinking: true conflicts with effort none. Reasoning appears separately in message.reasoning_content, or delta.reasoning_content when streaming. Only the final answer is in content.

{
  "model": "nullmoth-recon",
  "messages": [{"role": "user", "content": "What is 17 times 23?"}],
  "thinking": true,
  "reasoning_effort": "medium",
  "max_tokens": 8192,
  "stream": true
}

Reasoning and the answer share max_tokens and the output price. Medium uses up to 25% of max_tokens for thinking; High uses up to 45%. Medium is the default. With max_tokens=8192, the thinking budgets are 2,048 and 3,686 tokens. Unused thinking capacity remains available for the answer. The total maximum is 16,384 tokens.

Low is accepted as a compatibility alias for medium. These limits leave room for an answer, but do not guarantee its length or completeness. Very small budgets can still end without an answer. Only measured output is billed, including reasoning once. Without an explicit thinking flag, medium/high enables reasoning and none disables it.

One active generation and 20 requests per minute per account; four concurrent generations globally by default. Development credits are simulated, capped at $100 per account. No money is collected in development mode.

Ethereum USDC is the planned launch payment. Automatic Ethereum crediting is still pending. The existing Solana adapter is a separate test capability. Public checkout stays disabled until the selected payment flow is validated. A browser return URL never proves a payment.

Credit expiry, refunds, account recovery and final rates must be published before commercial launch.

Account & credits ↗

Continuous batching ≠ a Batch API.

vLLM can combine computation for independent concurrent requests through continuous batching. Aggregate throughput is not the speed of each individual request. Our own concurrent-load benchmark is needed to determine sustainable prices.

No public asynchronous Batch API, processing deadline or discounted batch rate is currently offered.