SPARROWCODES

Documentation

SparrowCodes speaks OpenAI's Chat Completions and Responses APIs and Anthropic's Messages API. Any OpenAI or Anthropic SDK, or tool that lets you set a base URL, works.

Quickstart

  1. Create an account and add credits from the Credits page.
  2. Create an API key under API keys. It is shown once, so store it in your secret manager.
  3. Set the base URL to https://api.sparrowcodes.com/v1 and use the key as the bearer token.
export SPARROW_API_KEY="sk-sc-v1-…"
curl https://api.sparrowcodes.com/v1/chat/completions \
  -H "Authorization: Bearer $SPARROW_API_KEY" \
  -d '{"model":"anthropic/claude-sonnet-5.5","messages":[{"role":"user","content":"Hello"}]}'

Authentication

Send Authorization: Bearer sk-sc-v1-… on every request. Keys belong to your account and spend from its balance. You can give a key a lifetime or monthly spending limit (monthly limits reset on the 1st, UTC), and disable it at any time; a disabled key is rejected within a second. Over the limit, requests fail with 402 key_limit_reached.

Anthropic SDKs send the key as x-api-key instead; that works too. Keys start with sk-sc-v1- so secret scanners can recognise them: if GitHub finds one of your keys in public code, we disable it within seconds, email the account's owners and admins, and send a key.leaked webhook.

Until an account makes its first top-up it can make 20 requests per minute, and one request can cost at most $0.50. Both limits lift after the first payment.

SDKs and tools

Point any OpenAI-compatible client at https://api.sparrowcodes.com/v1 and use a SparrowCodes model id, which always includes the provider (anthropic/claude-sonnet-5.5).

# pip install openai
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.sparrowcodes.com/v1", api_key=os.environ["SPARROW_API_KEY"])
reply = client.chat.completions.create(
    model="anthropic/claude-sonnet-5.5",
    messages=[{"role": "user", "content": "Hello"}],
)
print(reply.choices[0].message.content)

Coding tools that accept an OpenAI-compatible provider work the same way:

Claude Code
Set ANTHROPIC_BASE_URL=https://api.sparrowcodes.com and ANTHROPIC_AUTH_TOKEN to your key. See Anthropic API and Claude Code.
Cline
Settings → API Provider: OpenAI Compatible. Base URL https://api.sparrowcodes.com/v1, your SparrowCodes key, and a model id such as anthropic/claude-sonnet-5.5.
Continue
Add a model to config.yaml with provider: openai, apiBase: https://api.sparrowcodes.com/v1, apiKey and model: anthropic/claude-sonnet-5.5.
Aider
aider --model openai/anthropic/claude-sonnet-5.5 --openai-api-base https://api.sparrowcodes.com/v1 --openai-api-key $SPARROW_API_KEY
Cursor
Settings → Models: enter your SparrowCodes key as the OpenAI API key, turn on Override OpenAI Base URL with https://api.sparrowcodes.com/v1, and add the model id as a custom model. Some Cursor features always use Cursor's own models.

Chat completions

POST /chat/completions takes the same body as OpenAI: messages, tools, tool_choice, response_format, max_tokens or max_completion_tokens, reasoning_effort, stop and stream. Use a model id from the models page, such as openai/gpt-6.1-sol or x-ai/grok-4.7.

Providers differ. When a model does not support an option you sent, we remove it and tell you in the X-Sparrow-Warning response header instead of failing the request. For example, current Claude models ignore temperature.

Reasoning text, when a model returns it, arrives in message.reasoning (or delta.reasoning when streaming).

Streaming

Set "stream": true to receive server-sent events in OpenAI's chunk format, ending with data: [DONE]. The last chunk before [DONE] has empty choices and a usage object with the cost. If you disconnect early you are charged for what was generated up to that point.

Anthropic API and Claude Code

POST /v1/messages speaks Anthropic's Messages API, including streaming events, tools, images, PDFs, extended thinking and cache_control prompt caching. Use the Anthropic SDKs, or anything built on them, by changing the base URL to https://api.sparrowcodes.com. When the request goes to Claude, the body you sent reaches Anthropic unchanged; other models get a translation, so you can run Claude tools on any model.

# Claude Code
export ANTHROPIC_BASE_URL="https://api.sparrowcodes.com"
export ANTHROPIC_AUTH_TOKEN="sk-sc-v1-…"
export ANTHROPIC_MODEL="anthropic/claude-sonnet-5.5"
claude
# Python: pip install anthropic
import anthropic
client = anthropic.Anthropic(base_url="https://api.sparrowcodes.com", api_key="sk-sc-v1-…")
msg = client.messages.create(
    model="claude-sonnet-5-5",   # Anthropic's own ids work, as do ours
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)

Model names can be ours (anthropic/claude-sonnet-5.5) or the provider's own (claude-sonnet-5-5, with or without a date suffix). usage follows Anthropic's shape and adds cost in USD. POST /v1/messages/count_tokens returns an estimate. Errors use Anthropic's error shape, so the SDKs raise their usual exceptions.

Responses API

POST /v1/responses speaks OpenAI's Responses API, so client.responses.create and tools built on it work with any model, streamed or not, with function calling and structured output (text.format).

from openai import OpenAI
client = OpenAI(base_url="https://api.sparrowcodes.com/v1", api_key="sk-sc-v1-…")
r = client.responses.create(model="google/gemini-3.5-flash", input="Hello", instructions="Be brief.")
print(r.output_text)

It is stateless: we do not store responses, so previous_response_id and conversation are refused. Send the whole conversation in input, including earlier function_call and function_call_output items. Built-in tools such as web search are not available; define them as function tools.

Fallback models

Add models with up to five alternatives. If the first model fails before it starts answering, because a provider is down, rate-limited or overloaded, we try the next one. Errors caused by your request, such as invalid JSON in a tool call, are returned straight away.

{
  "model": "anthropic/claude-sonnet-5.5",
  "models": ["openai/gpt-6.1-sol", "x-ai/grok-4.7"],
  "messages": [{"role": "user", "content": "…"}]
}

The response headers X-Sparrow-Model and X-Sparrow-Provider show which one answered.

Provider routing

Many models are served by more than one provider (for example openai/gpt-oss-120b on Groq, Together and Fireworks, or Claude on Anthropic and Amazon Bedrock). By default we try them in our order and move a provider to the back while it is failing. Add a provider object to choose for yourself. It works on /chat/completions, /messages and /responses.

{
  "model": "openai/gpt-oss-120b",
  "messages": [{"role": "user", "content": "…"}],
  "provider": {
    "sort": "throughput",          // or "price", "latency"
    "order": ["groq", "together"], // try these first, in this order
    "ignore": ["fireworks"],       // never use these
    "data_collection": "deny",     // skip providers that may train on prompts
    "max_price": {"prompt": 1, "completion": 4}, // USD per 1M tokens
    "allow_fallbacks": true        // false: only the first matching provider
  }
}
FieldMeaning
sortprice cheapest first; latency lowest median time to first token over the last 7 days; throughput most tokens per second.
orderProviders to try first, in order. Others follow unless allow_fallbacks is false.
only / ignoreAllow-list or block-list of provider slugs.
data_collectiondeny skips providers whose terms let them train on API data.
max_priceSkip providers above these input (prompt) or output (completion) prices.
allow_fallbacksDefault true. False sends the request to one provider only.

If nothing matches, the request fails with 503 no_provider_matches and the message lists what was left out and why. The request log in your dashboard shows every attempt and the preferences that applied.

Auto routing

Set "model": "sparrow/auto" and we pick a model for each request: fast, low-cost models for short everyday prompts, and stronger ones when the request is long, includes code, uses tools, asks for high reasoning effort or looks like a hard analytical task. Requests with images only go to vision models, and requests with tools only to models that can call them.

You pay the chosen model's price. X-Sparrow-Model says which model answered, X-Sparrow-Auto-Tier the tier it started from (1 fast, 2 balanced, 3 frontier) and X-Sparrow-Auto-Reason why. If that model is unavailable, the next one in the tier answers.

Response cache

Send X-Sparrow-Cache: on (or "cache": true in the body) and an identical request from your account is answered from our cache instead of calling the model again. Cache hits are free, return in milliseconds, and are marked X-Sparrow-Cache: HIT with usage.cache_hit and usage.saved.

Entries last an hour by default; set X-Sparrow-Cache-TTL in seconds (up to 24 hours). The cache is per account and keyed on the whole request (model, messages, tools and options), so change any of them for a fresh answer. Use it for deterministic work such as classification, extraction or repeated prompts in tests, not for creative replies you want to vary.

curl https://api.sparrowcodes.com/v1/chat/completions \
  -H "Authorization: Bearer $SPARROW_API_KEY" \
  -H "X-Sparrow-Cache: on" \
  -d '{"model":"sparrow/auto","messages":[{"role":"user","content":"Classify: refund request or bug report? …"}]}'

Privacy

We don't store chat prompts or answers; usage records keep the model, token counts, cost and timing. Two controls in Settings → Privacy go further:

Mask personal data replaces email addresses, card numbers, phone numbers and secret keys in chat, image and video prompts with [EMAIL], [CARD], [PHONE] and [SECRET] before the request reaches the provider. To mask a single request instead, send X-Sparrow-Redact: on. Responses report the number of masked values in X-Sparrow-Redactions. Matching is pattern based, so treat it as a safety net rather than a guarantee.

Zero retention also stops us storing video prompts and turns off the response cache: requests sent with X-Sparrow-Cache: on go to the provider and return X-Sparrow-Cache: BYPASS.

Your own provider keys

Add your own Anthropic, OpenAI or xAI key in Settings → Provider keys and chat requests to that provider go through your key: they count against your provider quota and the provider bills you directly. We charge a small share of the model's list price per request from your credits, shown on that page, and responses carry X-Sparrow-BYOK: on.

Each key is checked with the provider before it is saved and stored encrypted. If the provider later rejects it, requests fail with 424 provider_key_rejected rather than quietly switching to our key. Speech, image and video models always use our keys.

Usage and cost

Every response includes usage.cost in US dollars, along with token counts and prompt_tokens_details.cached_tokens. Before a request starts we reserve its worst-case cost from your balance and release the unused part when it ends, so a request is refused up front rather than cut off halfway.

Each response has an X-Generation-Id header. Look it up with GET /generation?id=… for latency, provider and fallback details.

Text to speech

POST /audio/speech follows OpenAI's format, so client.audio.speech.create() works unchanged. Send model, voice, input, and optionally response_format (mp3, wav, flac, opus or pcm) and speed (0.5 to 2). The response is the audio file.

curl https://api.sparrowcodes.com/v1/audio/speech \
  -H "Authorization: Bearer $SPARROW_API_KEY" \
  -d '{"model":"kitten/tts-mini","voice":"Jasper","input":"Hello!"}' \
  --output hello.mp3

Every account gets free characters each day; after that you pay per character. GET /audio/models lists models, prices and free allowances, and GET /audio/voices?model= lists voices. Response headers show X-Sparrow-Characters, X-Sparrow-Cost-Inr and X-Sparrow-Free-Characters-Left.

Embeddings

POST /embeddings takes OpenAI's body: model, input as a string or an array of up to 2,048 strings, and optional dimensions and encoding_format (float or base64). You pay per input token at the provider's list price; the response's usage.cost shows what the call cost. List the models with GET /models?type=embedding.

curl https://api.sparrowcodes.com/v1/embeddings \
  -H "Authorization: Bearer $SPARROW_API_KEY" \
  -d '{"model":"openai/text-embedding-3-small","input":["first document","second document"]}'

Errors

StatusTypeWhat to do
400invalid_requestFix the request body; the message names the field.
401invalid_api_keyCheck the key, or whether it was disabled.
402insufficient_creditsAdd credits, or lower max_tokens.
402key_limit_reachedRaise the key's spending limit or use another key.
402trial_request_too_largeBefore your first top-up a request can cost at most $0.50. Lower max_tokens or add credits.
404model_not_foundUse an id from GET /models.
429rate_limitedSlow down and retry after a few seconds.
502provider_errorEvery provider failed. Retry, or add fallback models.
503no_provider_matchesYour provider preferences left nothing to call. Loosen them.

Other endpoints

  • GET /models: models you can call now, with prices in USD (and INR). No key needed. Add ?type=all for speech, image and video models.
  • GET /credits: your current balance.
  • GET /key: the calling key's name, limit and spend.
  • GET /generation?id=: details of one request.
Docs · SparrowCodes