NSLSolver
Concepts

How billing works

Balance is checked up front, deducted only on a successful solve, and updated live in memory. No refunds, no race conditions.

How billing works

The billing model is deliberately simple: you pay for the solves that returned a result.

Lifecycle of a /solve call

  1. Pre-check — The server reads your live balance from the in-memory ledger and rejects with 402 if it's below the per-call cost.
  2. Solve — The request is routed to a backend worker.
  3. Outcome:
    • Success (2xx). The cost is deducted after the response is flushed to your socket. The deduction is permanent and persisted to MySQL via an async writer.
    • Failure (4xx/5xx). Nothing happens to your balance.

Because the deduction is post-success, there is no refund path to reason about. A request either changed the balance, or it didn't.

Live balance

/balance reads the in-memory ledger directly, not the database. That means:

  • You see deductions reflected within milliseconds of a successful solve.
  • The persisted DB value lags by up to a few seconds (the async writer batches updates) — but the in-memory value is authoritative.
  • During a graceful shutdown the server flushes any pending deductions before exit.

Don't gate calls on /balance

The balance is stale the moment you read it. Use it for monitoring and pool sizing, not as a per-call gate. The server's pre-check is faster and accurate.

Concurrency safety

The in-memory ledger allows a small bounded overdraft — at most (concurrent in-flight) × (cost per solve). The pre-check is fast enough that the overdraft is generally negligible (well under $0.01 in practice).

That tradeoff buys you:

  • No DB hit on the success path of a solve.
  • No lock contention between concurrent solves on the same key.

Multiple keys

You can have multiple API keys per account, each with its own:

  • Balance
  • Allowed captcha types
  • CPM ceiling
  • IP allowlist

This is the recommended way to separate projects, teams, or environments — kill one key without affecting the others.

Low-balance notifications

If your account settings have lowBalanceAlert.enabled = true, the server fires an internal notification when:

  • Your balance falls to zero (always notified, regardless of threshold).
  • Your balance falls at or below your configured threshold (e.g. $5).

Notifications are cooldown-limited to one per 5 minutes per account, so a burst of solves won't spam you.

What's recorded

Every solve, whether successful or not, is logged with:

  • API key ID
  • User ID and email (for display in the dashboard)
  • Captcha type (slug form, e.g. cloudflare-turnstile)
  • Target URL
  • Status (success / failed) and any error message
  • Source IP
  • Duration in milliseconds
  • Cost (zero for failures)

These appear in the admin dashboard and feed your stats endpoints.

On this page