SpendGuard Security
Plain-English description of what happens to your data. Written for skeptics — if anything here is vague, that's a bug; ask us.
The one-sentence version
Your provider API key and your prompts pass *through* SpendGuard's memory while your request is being forwarded, and are never written to disk, never logged, and never stored. The only thing we keep is the metering math: when it happened, which provider, which model, how many tokens, how many dollars.
How it works
- You point your OpenAI-compatible client at
https://<proxy>/<your-spendguard-key>/<provider>/v1 and keep using your real provider API key as the key. Nothing about your client changes except the base URL.
- SpendGuard checks your SpendGuard key by comparing it against a salted
one-way hash. We don't store your SpendGuard key either — just the hash, so even we can't recover it.
- Your request is forwarded to the provider over HTTPS with the
Authorization header passed through byte-identical and the body untouched.
- The provider's response streams straight back to you. As it flows through,
we read the usage block (token counts) and compute the cost — exactly like glancing at a receipt as it's handed to you.
- We store one small row — timestamp, provider, model, tokens in/out, cost
in USD, whether the cost was exact or estimated, and the label you gave your SpendGuard key (e.g. "laptop"). Then we forget everything else.
What we store
- Timestamp of the request
- Provider name (
openai,xai,gemini,openrouter,custom) - Model name
- Prompt and completion token counts
- Cost in USD
- Whether the cost was exact (reported by the provider, e.g. xAI) or
estimated from our public rate table
- The label on your SpendGuard key, so you can tell devices apart
What we NEVER store
- Your provider API keys. You never paste one into our site or dashboard —
there is nowhere to paste one. The key lives in your client config, travels in the request header, gets forwarded, and is discarded.
- Authorization headers. Forwarded, never logged, never persisted.
- Your prompts, completions, or any request/response bodies. They exist in
RAM for the milliseconds the request is in flight, then they're gone.
- Anything else. If it's not in the "what we store" list above, we don't
have it. Our test suite verifies this mechanically: it sends requests with known marker text through the proxy and then searches every column of every database table for it.
Honest limitations
- In transit, in memory. While your request is being forwarded, its bytes
necessarily pass through the proxy's memory. We don't retain them, but someone with root access to the machine at that exact moment could theoretically observe them. Run SpendGuard on hardware you trust — it's designed for your own VPS, and the code is small enough to audit.
- Key in the URL. Your SpendGuard key travels in the request path — that's
what makes it work with unmodified OpenAI clients. Always use HTTPS in production so the path is encrypted in transit. Keys are free, unlimited, and revocable: sgadmin.py revoke-key <label> kills one instantly.
- TLS. Proxy → provider is always HTTPS. Put TLS on the proxy itself
(Caddy or Nginx Proxy Manager in front) — never expose the plain HTTP port to the internet.
- Estimates. Costs computed from our public rate table are labeled
estimated in the database and on the dashboard. xAI reports the exact billed cost on every response; we use that whenever it's present.
What we will never do
- Ask for your provider API keys. There is no field for them, no flow that
needs them, no reason to have them.
- Send your data to third parties. The only network calls the proxy makes are
to the provider you chose, carrying the request you made.
- Log request bodies "temporarily for debugging." The code path doesn't exist.