Developer integrations

SingIt with LiteLLM

Python model calls with a capped SingIt API key.

Why

LiteLLM gives you one call shape for many models. With SingIt, the agent's key has a daily cap, a per-request cap and an expiry, which your wallet signs. The key can use no more than that. Past a cap, the call is refused and that call is not charged.

The limits apply to calls made with that key to SingIt. They do not limit what an agent spends anywhere else, and they are separate from any budget you set in LiteLLM.

Model calls are paid from a prepaid SingIt balance the owner tops up in the SingIt app (Settings, API keys).

Install

pip install litellm

Make a key in the SingIt app (Settings, API keys) and keep it as SINGIT_API_KEY. Use LiteLLM's OpenAI-compatible provider: model openai/<SingIt model id>, api_base https://app.singitai.app/v1.

There is no SingIt-specific LiteLLM package, and you do not need one for this route.

Code

import os
import litellm

response = litellm.completion(
    model="openai/" + os.environ.get("SINGIT_MODEL", "deepseek-v4.1-flash"),
    api_base=os.environ.get("SINGIT_BASE_URL", "https://app.singitai.app/v1"),
    api_key=os.environ["SINGIT_API_KEY"],
    messages=[{"role": "user", "content": "Reply with one word: pong"}],
    max_tokens=200,
    num_retries=0,
)
print(response.choices[0].message.content)

Checked 2 November 2026 against a local test server that returns SingIt's error responses (langchain-openai 1.7.3, litellm 1.106.6, openai-agents 0.20.0). Not run against the live service.

What happens when the limit is exceeded

The call is refused before it is sent on, and that call is not charged. LiteLLM maps the error to its usual exceptions (see below).

What happenedHTTPerror.codeWhat to do
The key's daily cap is used up (counting calls still running). Message: "This key's daily limit of 1 USDC is used up, counting requests still running. It starts again at 00:00 UTC, or raise it with a new key." (the number is the key's cap)429insufficient_quotaWait for 00:00 UTC, or make a new key with a higher cap
One request would cost more than the per-request cap400over_request_limitLower max_tokens, send less input (shorter history, fewer or smaller tools), pick a cheaper model, or make a key with a higher per-request cap
More than 60 requests a minute on one key429rate_limit_exceededSlow down and retry
Key wrong, revoked or expired401invalid_api_keyMake a new key
The SingIt balance is too low for the request (and automatic top-ups are off or refused)402balance_lowTop up in the SingIt app (Settings, API keys)
Payments are paused on SingIt's side503payments_pausedTry again later

Pass num_retries=0 so a refused call is not retried. A daily-cap 429 raises litellm.RateLimitError; a 400 over_request_limit raises BadRequestError; a 401 raises AuthenticationError. A 503 payments_paused raises ServiceUnavailableError. A router fallback to another SingIt model uses the same key, so the same cap applies and it gets the same 429.

Where the limit is enforced:

  • Key caps (daily and per request) are checked by SingIt's server, not onchain, on Base and on Solana.
  • On Base, the owner's allowance is an onchain limiter contract with its limits fixed in it. It limits what SingIt can buy from your wallet (for example balance top-ups and search), not each model call a key makes.
  • On Solana, SingIt's server checks the daily limit, the per-purchase limit and the expiry. The chain enforces only the total you approved. The owner can stop new purchases from the app, including balance top-ups; revoking the delegation removes the onchain approval.

Revoking a key takes no wallet signature and is immediate.

Tools and real streaming work only when SingIt's server has its proxy on. This has not been checked live. A refusal always comes before a stream starts, as a normal HTTP error. A stream that breaks just ends, without an error event or a final completion marker; framework handling of a broken stream has not been checked. A started stream is charged for its cost or, if cost is unavailable, its reserved amount within the per-request cap.

A failed call may leave an automatic balance top-up as prepaid credit; the top-up is not undone.

Paying from your own wallet over x402 instead?

The Python x402 SDK offers a chat() call. Its limits are client-side and its daily counter is in memory, resetting when the process restarts. No Python adapter exists for this framework. See the python-x402 example.

Runnable code · Free-route and MCP snippets · SingIt API key documentation