Skip to content

Provider Adapters

Provider adapters wrap AI provider clients so applications can keep their normal provider calls while Spendware adds preflight checks, usage extraction, logging, and runtime context.

Supported Surfaces

  • OpenAI: responses, chat completions, and parse surfaces.
  • Anthropic: messages and streaming messages.
  • Gemini: content generation, interaction calls, and chat send methods.
  • Azure OpenAI and OpenAI-compatible clients.
  • Bedrock where package support is installed.

Example

curl "$SPENDWARE_BASE_URL/api/v1/usage/preflight-with-key" \
  -H "Content-Type: application/json" \
  -d '{"key":"SPENDWARE_CUSTOMER_KEY","service_provider_name":"openai","service_name":"gpt-4o","input_tokens":120,"output_tokens":45}'
import os

from openai import OpenAI
from spendware_provider_sdk import create_spendware_config, wrap_openai_client
from spendware_provider_sdk.core.adapter_types import AdapterCommonOptions
from spendware_provider_sdk.core.types import KeyAuthConfig

openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
config = create_spendware_config(
    spendware_base_url="SPENDWARE_BASE_URL",
    auth=KeyAuthConfig(customer_key="SPENDWARE_CUSTOMER_KEY"),
)
wrapped = wrap_openai_client(openai_client, AdapterCommonOptions(config=config))
response = wrapped.client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
    spendware={"runtime_context": {"feature": "chat"}},
)
wrapped.shutdown()
import OpenAI from "openai";
import { createSpendwareConfig, wrapOpenAIClient } from "@spendware/provider-adapters-sdk";

const openaiClient = new OpenAI({ apiKey: "OPENAI_API_KEY" });
const config = createSpendwareConfig({
  spendwareBaseUrl: "SPENDWARE_BASE_URL",
  auth: { mode: "customer_key", customerKey: "SPENDWARE_CUSTOMER_KEY" },
});
const wrapped = wrapOpenAIClient(openaiClient, { config });
const response = await wrapped.client.chat.completions.create(
  {
    model: "gpt-4o",
    messages: [{ role: "user", content: "Hello" }],
  },
  { spendware: { runtimeContext: { feature: "chat" } } },
);
await wrapped.shutdown();

Runtime Context

Use runtime context resolvers or per-call overrides when one process serves multiple tenants. Prefer external project and customer IDs when internal Spendware IDs are not available.

Common Errors

  • Forgetting shutdown() can leave async usage logs queued.
  • Dry-run mode skips backend calls by design.
  • Missing customer/project context can prevent usage attribution.