Surface coverage
What happens when you call each surface through Solwyn — priced, recorded-but-unpriced, untracked under your on_unmetered posture, fail-loud, or structural pass-through.
Solwyn wraps the client you already use, so you keep calling your provider's own methods. When a call reaches the wrapper, exactly one thing happens to it: Solwyn either meters it (budget check plus a cost event), records it without a price, treats it as untracked under your on_unmetered posture (warn once by default), refuses it, or — for a structural attribute that carries no spend — passes it through in silence. This page lists every surface and the posture it gets.
One invariant holds across all of them: Solwyn is a wrapper, not a proxy, so the call still goes directly to the provider, and only bounded metadata — integer and float quantities (token counts, image counts, whole-second durations, character counts) and short selector strings (resolution, quality) — leaves your process. Never a prompt, never media bytes, never a transcript, never generated content. See Privacy for the full wire contract.
The five postures
| Posture | What Solwyn does | Cost event |
|---|---|---|
| Priced | Budget-checks before dispatch, then reports usage so the Cloud API can price it | Yes, priced |
| Recorded but unpriced | Records the call when the billable quantity is unobservable — never a fabricated $0 | Yes, unpriced |
| Untracked — your posture decides | warn (default): logs one warning per surface per process, then forwards the call. raise: refuses it with UntrackedSpendSurfaceError before any provider I/O. allow: forwards it silently. | No |
| Fails loud | Raises rather than let a spend surface bypass tracking silently | No (call refused) |
| Structural pass-through | Forwards attributes that carry no spend, and hands back resource namespaces as guarded objects whose members are classified one by one | No |
SDK v0.6.0+: every public attribute path on a wrapped client resolves to one of these. Before 0.6.0 a short allow-list of billable surfaces warned and everything else — files, batches, models.list, the Responses helpers — passed in silence. Now the whole reachable graph is classified, and solwyn.coverage(client) returns the classification for the client you actually hold. See Coverage controls.
Priced
Budget-checked before the request — an over-budget call is denied before the provider is reached — then recorded as a cost event tagged with a modality, which the Cloud API prices per-token or per-unit from the model's price card.
| Modality | Surfaces | Priced on |
|---|---|---|
| chat | chat.completions.create (OpenAI, Together, every OpenAI-compatible endpoint), messages.create (Anthropic), models.generate_content (Google), converse / converse_stream (Bedrock) | provider-reported token counts |
| chat — Responses API | responses.create, responses.parse, and the responses.stream() helper on native OpenAI and Azure OpenAI (SDK v0.6.0+; modality text) — see The Responses API | provider-reported token counts, read from the response or the stream's terminal response.completed event; when usage is missing or zeroed, a marked input-only estimate (is_estimated) so the call is never a silent $0 |
embedding | embeddings.create (OpenAI, compat, native Together), models.embed_content (Google) | input tokens (usage.prompt_tokens; Google exposes no usage, so counts are length-estimated and flagged is_estimated) |
image | images.generate / images.edit (OpenAI, compat, native Together), models.generate_images (Google Imagen); image-output chat models (e.g. gemini-3-pro-image) | token buckets for token-billed models (OpenAI gpt-image, Gemini image-output); request-derived image count × per-image rate for compat, Together, and Imagen |
audio | audio.transcriptions.create, audio.speech.create (OpenAI + compat, incl. Groq); Gemini TTS / native-audio via generate_content | transcription: token buckets (gpt-4o-transcribe) or whole-second duration on a JSON response_format (whisper-1, Groq per-hour); speech: input character count, measured inside the privacy firewall (tts-1 / tts-1-hd, Groq Orpheus) |
video | videos.create (OpenAI Sora), models.generate_videos (Google Veo) | requested duration × resolution variant's per-second rate |
Video generation is asynchronous and the job carries no usage, so — because neither provider charges for a failed or blocked generation — video billing settles at initiation: the cost event is recorded at request time and always flagged is_estimated, a deliberate, conservative over-count. Its pre-flight budget check is nonetheless exact, so an over-budget request is denied before the provider is called.
For each modality, only the quantities and selectors leave your process — never the prompt, never a reference image, never the returned bytes.
Recorded but unpriced
Some calls are genuinely billable but expose no observable quantity to price on. Rather than invent a number or fabricate a $0, Solwyn records the event and leaves it unpriced on the dashboard — an honesty lane, visible but explicitly not costed. This is a settlement outcome of a priced surface, not a separate classification:
- A
whisper-1or compat transcription with a non-JSONresponse_format(text,srt,vtt) — the provider returns no usage block. The SDK warns once suggesting a JSONresponse_format. - A Veo
generate_videoscall with noconfig.duration_seconds— Google publishes no default duration, so there is no basis to price on and none is guessed. - Any unit-priced call whose quantity could not be observed.
- A Bedrock call whose model is an opaque ARN the Cloud API cannot resolve to a price card.
- Zero-cost local providers (
ollama,vllm,lmstudio) and the genericopenai_compatiblecatch-all — providers with no price book, where any model is recorded for visibility and never silently costed.
Untracked — your posture decides
A capability Solwyn has reviewed and does not meter yet, or one it has never seen (typically new in a provider-SDK release), follows on_unmetered. Under the default warn, the SDK logs one WARNING per provider, client shape, sync/async mode, and dotted surface path per process — naming only the provider and the surface, never request data — and then runs the call untracked: no budget check, no cost event, and an advisory report to Solwyn Cloud so the Providers tab can show what your code touched. raise refuses the call before any provider I/O with UntrackedSpendSurfaceError; allow restores silence. An exact token in acknowledge_untracked exempts one leaf from all three.
Representative untracked leaves — the full list for your client comes from solwyn.coverage(client):
- OpenAI, Azure OpenAI, and every OpenAI-compatible endpoint:
moderations.create,models.list,files.*,batches.*,fine_tuning.*,vector_stores.*, the non-metered Responses leaves (responses.retrieve,.delete,.cancel,.compact,.connect,.input_items.list,.input_tokens.count),audio.translations.create, thewith_raw_response/with_streaming_responsefamilies, and theadmin.*tree. The token-billed TTS modelgpt-4o-mini-ttsreturns no usage of any kind and is untracked under the conditional tokenaudio.speech.create:gpt-4o-mini-tts. On a compatible endpoint other than Azure, every Responses leaf is untracked —create/parse/streamincluded: they are not budget-checked and produce no cost event (SDK v0.6.0+). - Anthropic:
messages.count_tokens,models.*,completions.create(pre-1.0 clients only), and Anthropic 1.0's stablefiles.*andskills.*, plus thebeta.*tree. - Google (
google-genai):files.*,caches.*,batches.*,tunings.*,models.count_tokens,live.connect, and theiraio.*mirrors. - Amazon Bedrock:
apply_guardrail,count_tokens,get_async_invoke,list_async_invokes, and the boto3 plumbing (get_paginator,get_waiter, ...). - Together (native client):
completions,rerank,code_interpreter,evals,batches,files,fine_tuning,endpoints, andwhoami. See Together AI.
Some untracked rules describe an escape rather than an operation — with_options, copy, and the raw get / post / request verbs on OpenAI-dialect and Anthropic clients, aio on Google, the audio.translations resource itself. Their capability scope (client, resource, raw_response, arbitrary_endpoint) appears in the warning, and acknowledging one at exactly its own path hands back the raw provider object.
Fails loud
A primary spend surface Solwyn cannot track without bypassing the budget or buffering customer content raises instead of running silently untracked:
- On Bedrock,
invoke_model,invoke_model_with_response_stream, andstart_async_invokeraiseConfigurationError. Their usage lives inside a consume-once body alongside response content (invoke_model), or lands out-of-band in S3 (start_async_invoke), so it cannot be extracted without violating the privacy boundary. Useconverse/converse_stream, or call the unwrapped boto3 client directly for deliberately untracked calls. videos.createon an OpenAI-compatible or native Together client raisesUnsupportedSurfaceError: Solwyn's video interception is wired for OpenAI's Sora only, and no video seam exists on the OpenAI-compatible dialect those clients speak — so the call fails loud rather than passing through as if untracked.- The same rule holds for any media surface an adapter serves no seam for —
embeddings.createon a wrapped Anthropic client, for instance, raisesUnsupportedSurfaceErrorrather than running untracked. - A metered Responses call in a shape Solwyn cannot meter —
background=True, a streamingparse, or anextra_bodythat overridesmodel,input,instructions,max_output_tokens, orstream— raisesConfigurationErrorbefore the budget check. See The Responses API. - Under
on_unmetered="raise", every untracked leaf above raisesUntrackedSpendSurfaceErrorbefore any provider I/O — the opt-in strict posture. See Coverage controls.
Structural pass-through
Two kinds of attribute are forwarded without a warning in any posture, because they cannot carry spend:
- Metadata and infrastructure —
base_url,api_key,timeout,close, and the like. These are the only attributes that are unconditionally silent. - Namespaces —
audio,beta,responses,chat, and every other resource container. Accessing one returns a guarded resource, not the raw object; each member you then reach is classified on its own. Access to a parent never grants its descendants, and thewithprotocol is not forwarded on a guard.
Private attributes (any _-prefixed name that is not _solwyn_) belong to the provider client and bypass the guard entirely.
Deliberately-unbilled models
When a pre-flight budget check names a model the Cloud API has deliberately chosen not to price, the API answers the check with a structured 422. The SDK treats that like any non-2xx and resolves it through the standard fail-open path: the call is allowed and proceeds untracked. Solwyn never blocks a call solely because it cannot yet price it.
What leaves your process
Across every posture above, the privacy boundary is identical: bounded metadata only — the MetadataEvent counts, durations, character counts, and selector strings, plus structural labels and any tags you attach yourself. An untracked surface adds one more payload, the advisory report: provider, client shape, the dotted surface path, and an occurrence count — no model names, arguments, or content. No prompt, no media bytes, no transcript, no generated content ever leaves your process. Per-provider detail lives on each provider page.