{"service":{"name":"Spendline","category":"AI cost controls for B2B software companies / financial control layer","summary":"Spendline is a financial control layer for production AI spend. It routes supported AI requests, records attributed costs and applies configured controls, and covers only traffic actually routed through it. Your application supplies the customer, agent, workflow and team labels; configured budgets and policies are checked before a supported request is forwarded.","mechanism":"Request-path proxy. Applications change their provider base URL to Spendline and keep their own provider API keys. Attribution travels as HTTP headers.","differentiator":"Financial control, not engineering observability. Strict budgets refuse a supported request whose estimated cost would exceed a limit (HTTP 402) before it reaches the provider; actual response cost can differ from the estimate. Costs are kept in an append-only ledger with an owner-run month close.","contact":"fida@spendline.ai"},"canonical_origin":"https://staging.spendline.ai","request_shapes":[{"id":"openai_chat_completions","label":"OpenAI chat-completions","endpoint":"/v1/chat/completions","sdk_base_url":"https://staging.spendline.ai/v1","sdk_note":"Set the OpenAI SDK baseURL/base_url to https://staging.spendline.ai/v1. WITH /v1. The SDK appends /chat/completions itself.","streaming":true,"providers":["openai","google","xai","mistral","deepseek","qwen","together","fireworks","groq"],"routing":"The model name selects the provider (gpt-* → OpenAI, gemini-* → Google, grok-* → xAI, mistral-* → Mistral, …).","full_endpoint":"https://staging.spendline.ai/v1/chat/completions"},{"id":"anthropic_messages","label":"Anthropic messages","endpoint":"/v1/messages","sdk_base_url":"https://staging.spendline.ai","sdk_note":"Set the Anthropic SDK baseURL to https://staging.spendline.ai. WITHOUT /v1. The Anthropic SDK appends /v1/messages itself. This asymmetry with the OpenAI SDK is real; do not \"fix\" it.","streaming":true,"providers":["anthropic"],"routing":"Claude models.","full_endpoint":"https://staging.spendline.ai/v1/messages"},{"id":"openai_responses","label":"OpenAI Responses API","endpoint":"/v1/responses","sdk_base_url":"https://staging.spendline.ai/v1","sdk_note":"Same base URL as chat-completions.","streaming":false,"streaming_note":"stream: true is rejected with a clear error. Non-streaming only.","providers":["openai"],"routing":"OpenAI models only. Built-in tools such as web_search work and their cost is included in recorded spend.","full_endpoint":"https://staging.spendline.ai/v1/responses"}],"unsupported_shapes":["embeddings","image generation","audio / speech","vector or knowledge-base search","Google's native generateContent shape (use the OpenAI-compatible path instead)"],"providers":[{"key":"openai","label":"OpenAI","shape":"openai_chat_completions","also":["openai_responses"]},{"key":"anthropic","label":"Anthropic","shape":"anthropic_messages"},{"key":"google","label":"Google Gemini","shape":"openai_chat_completions"},{"key":"xai","label":"xAI","shape":"openai_chat_completions"},{"key":"mistral","label":"Mistral","shape":"openai_chat_completions"},{"key":"deepseek","label":"DeepSeek","shape":"openai_chat_completions"},{"key":"qwen","label":"Alibaba Qwen","shape":"openai_chat_completions"},{"key":"together","label":"Together AI","shape":"openai_chat_completions"},{"key":"fireworks","label":"Fireworks AI","shape":"openai_chat_completions"},{"key":"groq","label":"Groq","shape":"openai_chat_completions"}],"attribution_headers":{"auth":{"header":"x-spendline-key","value":"The Spendline API key, from env (SPENDLINE_API_KEY).","critical":"NEVER send the Spendline key as x-api-key. Anthropic uses x-api-key for the Claude provider key, so the Spendline key would be forwarded to Anthropic and rejected."},"required_when_enforced":[{"header":"x-agent-id","value":"Stable name of the bot/agent/feature making the call, e.g. support-bot.","cardinality":"One per agent. Not per request."},{"header":"x-customer-id","value":"The end customer this request is billable to.","cardinality":"PER REQUEST. A hardcoded value makes per-customer cost attribution useless, thread it from request context."},{"header":"x-spendline-tags","value":"JSON object that must include a cost-centre key: one of cost_center, costCenter, department, or team. Example: {\"team\":\"support\",\"env\":\"prod\"}","cardinality":"Per call site or per request."}],"optional":[{"header":"x-workflow-id","value":"Groups a multi-step run."},{"header":"x-step-name","value":"Labels a step within a workflow."},{"header":"x-source-route","value":"The application route that triggered the call."}]},"response_contract":[{"status":200,"meaning":"Forwarded and recorded.","agent_action":"Done."},{"status":400,"error_type":"missing_required_attribution","meaning":"Attribution enforcement is on and a required header is missing.","agent_action":"Add x-agent-id, x-customer-id and x-spendline-tags (with a cost-centre key)."},{"status":401,"meaning":"The Spendline key is missing or invalid.","agent_action":"Check SPENDLINE_API_KEY. Do NOT fall back to the provider."},{"status":402,"meaning":"A budget blocked this call before any spend occurred.","agent_action":"This is correct, intended behaviour. Surface it as an error. NEVER retry against the provider directly, that defeats the entire product."},{"status":403,"meaning":"A policy or governance rule blocked the call.","agent_action":"Surface it. NEVER route around it."},{"status":429,"meaning":"Rate limited.","agent_action":"Back off and retry."},{"status":"5xx / network error / timeout","meaning":"Spendline is unreachable or failed.","agent_action":"Retry once directly against the provider so the application stays up. This is the ONLY case where bypassing Spendline is correct. A request sent directly to the provider is outside Spendline's budget checks and cost records."}],"capabilities":[{"id":"attribution","name":"Per-customer / agent / workflow cost attribution","detail":"Each supported request routed through Spendline is written to an append-only ledger (ai_calls) with the customer, agent, workflow, step, team and source route labels the application supplied, and a server-controlled timestamp deciding which month it lands in. Requests without labels are recorded but leave gaps in customer reporting; requests sent directly to a provider are not recorded."},{"id":"hierarchical_budgets","name":"Hierarchical budgets with pre-spend enforcement","detail":"Budgets nest org → team → agent → customer. The check happens BEFORE the upstream call, against recorded spend, in-flight reservations and an estimate of this request (max_tokens, or a default output allowance when it is unset). In strict mode a request whose estimate would exceed the limit returns HTTP 402 and costs nothing. Final response cost can exceed the estimate, so a long response can take spend past the limit."},{"id":"flat_budgets","name":"Account-level budget guardrails","detail":"A simpler flat monthly cap per account, evaluated on every proxied call."},{"id":"policies","name":"Policy engine","detail":"Model block lists, model allow-lists and per-model token caps, each account-wide or scoped to an agent or customer with the same scope object reroute rules use. A model block or allow-list always hard-blocks (HTTP 403); a token cap can instead be set to warn-only. A scoped policy also holds calls that carry no attribution, so a missing header is never a way around it. Supports one-time allow exceptions."},{"id":"governance","name":"Production governance rules","detail":"Environment-aware guardrails applied on top of budgets and policies."},{"id":"rerouting","name":"Cost optimizer and cross-provider rerouting","detail":"Rules can reroute a request to a cheaper or cross-provider model before it is sent, using the account's own encrypted provider keys."},{"id":"month_close","name":"AI month close and reconciliation","detail":"The append-only ledger is closed month by month: open → closed → reconciled. Closing seals the month: its sealed total never changes, and corrections after close are new ledger_adjustments rows (shown as a separate corrected total), never mutations of original ai_calls. An owner can upload a provider invoice CSV and Spendline compares its total with the corrected month total, filing any difference as one reconciliation line. It compares totals; it does not match invoice line items. Validate, close and reconcile are owner actions in the dashboard and API, deliberately not available to agents."},{"id":"margin","name":"Per-customer margin analytics","detail":"Where you share revenue data (entered manually or imported by CSV), customer revenue minus attributed AI cost over the same period: margin after AI cost. Other delivery costs are not included."},{"id":"alerting","name":"Anomaly detection and runaway-spend alerts","detail":"Automatic hourly budget burn-rate forecasting and hourly runaway-agent anomaly detection (also runnable on demand from the dashboard), delivered to a Slack or Discord webhook. No email delivery."},{"id":"audit","name":"Append-only audit trail","detail":"budget_audit_log and month_close_audit_log record every governance change with actor and tenant, written in the same operation as the change itself."}],"authorization":{"agent_may_alone":["Read this manifest and every public document under /agents/.","List supported providers, request shapes and models.","Decide whether Spendline fits the requirement.","Write the integration into application code (base URL + attribution headers).","Start an onboarding request that emails a human for authorization.","Poll the status of its own onboarding request.","With a Spendline key: read spend, budgets, policies and integration status."],"requires_human_authorization":[{"action":"Creating a Spendline account","why":"The human sets their own password and accepts the terms. An agent must never choose a credential for a person.","how":"A new team starts with a guided pilot booked on a call at https://staging.spendline.ai/book/; a person invited to an existing account accepts the invite in a browser. An agent never creates the account."},{"action":"Issuing an API key to an agent","why":"A key is standing access to a financial control plane.","how":"The human explicitly approves the specific request in the browser (device-authorization flow), then the key is released once."},{"action":"Adding or changing a payment method, or subscribing to a paid plan","why":"Financial commitment.","how":"Human-only, in the dashboard. There is no API for an agent to do this."},{"action":"Storing a provider API key (OpenAI, Anthropic, …) in Spendline","why":"A provider key is a live spending credential.","how":"Human-only, in the dashboard."},{"action":"Raising or deleting a budget, or overriding a budget block","why":"It increases or removes a spending limit, the exact control the product exists to hold.","how":"Owner authority in the dashboard/API. Deliberately absent from the MCP tool surface."},{"action":"Closing, reopening or reconciling a month","why":"It seals a financial period and writes to the audit trail.","how":"Owner authority. Deliberately absent from the MCP tool surface."}],"never_permitted":["An agent obtaining the account owner/root key through any programmatic flow. Onboarding issues a scoped child key only.","An agent bypassing a 402 budget block or 403 policy block by calling the provider directly.","Any credential in a URL or query string. Spendline rejects requests whose query string names a credential."]},"commercial":{"how_to_start":"A guided 30-day free pilot, scoped on a 30-minute call. Public self-serve signup is not the way in for new teams; people invited to an existing account keep the invite flow.","book_a_call":"https://staging.spendline.ai/book/","pricing":"No public Spendline price. Paid pricing combines a platform fee with a capped charge based on managed AI spend; scope, included features and paid terms are agreed before the pilot starts. There is no Spendline subscription fee during the pilot; model-provider charges still apply.","model_prices":"https://staging.spendline.ai/pricing/ lists model-provider token rates as reference data. They are not Spendline fees."},"documentation":{"index":"https://staging.spendline.ai/agents/index.md","openapi":"https://staging.spendline.ai/openapi.json","mcp":"https://staging.spendline.ai/.well-known/mcp.json","full_corpus":"https://staging.spendline.ai/llms-full.txt"}}