Developer integrations

SingIt with LangChain (Python)

Python model calls with a capped SingIt API key.

Why

With SingIt, you make a key for the agent and sign its terms with your wallet: a daily cap, a per-request cap and an expiry. The key can use no more than that. When a cap is reached, the next 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.

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

Install

pip install langchain-openai

Make a key in the SingIt app (Settings, API keys) and keep it in your environment as SINGIT_API_KEY. Point ChatOpenAI at https://app.singitai.app/v1.

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

Code

import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model=os.environ.get("SINGIT_MODEL", "deepseek-v4.1-flash"),
    base_url=os.environ.get("SINGIT_BASE_URL", "https://app.singitai.app/v1"),
    api_key=os.environ["SINGIT_API_KEY"],
    max_retries=0,
    max_tokens=200,
)
print(llm.invoke("Reply with one word: pong").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. Your agent sees a normal OpenAI-style error, so LangChain raises the usual openai exception.

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

Set max_retries=0 on ChatOpenAI: by default it retries a 429, and a refused call will be refused again. With max_retries=0 LangChain raises openai.RateLimitError (a langchain_openai subclass of it) with code == "insufficient_quota".

Tools: bind_tools sends tools. They work only when SingIt's server has its proxy on; otherwise the call is refused with 400 tools_unsupported. Production status is not verified, so check GET /v1/models and run one small call first.

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. Its daily cap, per-purchase cap and expiry are fixed in the contract. 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.
  • On Solana: the owner can stop new purchases from the app, including balance top-ups. Revoking the delegation removes the onchain approval. Revoking a key stops that key at once.

Revoking a key takes no wallet signature and is immediate. A key cannot move funds or change limits.

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