# Seams — every page, one file > Generated from the same content the pages render. Source: https://ourseams.com --- source: https://ourseams.com/ # Ship the billing page your AI product needs. Meter every call, cap every user, bill in your own brand. Point your base URL at Seams and it works in five minutes. Hard spend caps that stop mid-stream. No metering vendor can do this. ## Everyone builds this page. It is the same every time. Cursor, Anthropic, OpenAI, Replit: a usage number, a chart, a table of calls, a card on file. Four companies, four teams, four quarters of engineering, one design. ## Four pages, in your brand, on your domain. Your customer never sees our name. The portal takes your product name, your colour and your logo, and it is the only surface their end users touch. - **Members** — Who is on the account, what each of them may spend, and how to cut one off. Not built yet. - **Usage** — Calls, tokens and cost per person per model, down to the request. Built, on metered rows. - **Spending** — What the plan includes, how much of it is left, and the user's own ceiling past it. Built, on metered rows. - **Billing** — The plan, the period's usage itemised by quota pool, and the invoices. Built, on metered rows. ## Five minutes, and one of them is reading. Point an OpenAI-shaped client at our base URL with an end user's key. Nothing else in your application changes. ### curl ```bash curl https://gw.ourseams.com/v1/chat/completions \ -H "Authorization: Bearer ak_live_…" \ -H "Content-Type: application/json" \ -d '{"model":"mock/fast","messages":[{"role":"user","content":"hello"}]}' ``` ### TypeScript ```ts import OpenAI from "openai" // the only line that changes. your client, our base url, your end user's key const client = new OpenAI({ baseURL: "https://gw.ourseams.com/v1", apiKey: endUserKey, }) const stream = await client.chat.completions.create({ model: "mock/fast", messages: [{ role: "user", content: "hello" }], stream: true, }) for await (const chunk of stream) { // ours, and non-standard: the cap fired and the stream ended early if (chunk.choices[0]?.finish_reason === "spend_cap_exceeded") break } ``` ### MCP ```json { "mcpServers": { "seams": { "command": "npx", "args": ["-y", "@seams/mcp"], "env": { "SEAMS_API_KEY": "ak_live_…" } } } } ``` ## The stream stops mid-sentence. A metering vendor finds out what you spent after the request finished. We hold the money before it starts and keep checking while it runs. - **reserve** — hold the money on the wallet before the request leaves, in one atomic step - **stream** — re-check accrued spend every 16 chunks, and every 250ms - **abort** — at 98% of the hold: close the upstream socket, send a usage block, send [DONE] - **settle** — release the hold, write one ledger row, reconcile to the cent A stream can end with finish_reason "spend_cap_exceeded" and a usage block. It is not an error — the status was already 200 and cannot be retracted. Most caps never abort. When the remaining budget can be turned into a token count we clamp max_tokens instead, and the finish_reason is the ordinary "length". ## We do not take over your stack. - **Your router** — Send us the model you already chose. We do not pick it for you. - **Your auth** — Your users, your sign-in. We attribute spend by key, never by a header you set. - **Your keys** — Your provider account, your rate limits, your bill. We hold the ciphertext. - **Your prices** — You set the markup. What your customers pay is a number you own. ### And what we do not do - Invoicing, revenue recognition, dunning and tax. Stripe does those; we do not wrap them. - Merchant of record. Your customers pay you, and the legal relationship stays yours. - A routing product. One provider in v1, and no builder for picking between them. - Your prompts and completions. There is no column for a message body and no code path that writes one. --- source: https://ourseams.com/blog --- source: https://ourseams.com/docs # Docs The quickstarts live at /quickstart. Mint one key per end user at signup — step 2 on every path. a shared key with an end-user header would be forgeable from the tenant's own code, and would make the spend cap advisory rather than enforced. --- source: https://ourseams.com/pricing # Free where our cost is zero. Three paths, split by what a call costs us rather than by which features we withheld. **Draft. These numbers are not final and will move before anyone is charged.** ## Test mode — $0 forever The mock provider costs us nothing, so it costs you nothing. No card, no limit, no expiry. - Unlimited calls against the mock provider - All four end-user pages, in your brand - Real wallets, real holds, real ledger rows - About $1 of real inference on the cheapest models, until you add a card ## Bring your own key — $29 per month You pay your provider directly. We never bought your tokens, so there is nothing to mark up. - Free under 100,000 calls a month - Your provider keys, encrypted; we hold the ciphertext - Hard caps and mid-stream aborts on every key - No ceiling on spend, because none of it is ours ## Managed — $29 + 5% per month, plus markup on inference We buy the tokens and send one invoice. The markup is the price of not holding a provider account. - Everything in bring your own key - One invoice for platform and inference together - A dollar-capped trial before the first payment, not a 14-day one - Your own markup on top, which is yours to keep ## Every step of the upgrade is self-serve. 1. Sign in with GitHub. A tenant, a wallet and a key exist before you have filled anything in. 2. Add a card in the console when the free inference runs out. No call, no quote, no form. 3. Move between the three paths by adding or removing a provider key. Nothing is migrated. ## What is not in the price We do not invoice your customers, recognise your revenue, chase their failed payments or work out their tax. We are not the merchant of record, so the money and the legal relationship stay yours. --- source: https://ourseams.com/quickstart # Quickstart Three steps: point the base URL, mint a key per end user, call with that key. Pick curl, TypeScript or Python on the next page. --- source: https://ourseams.com/quickstart/curl # curl Point the base URL, mint a key per end user, call with that key. ``` curl https://api.ourseams.com/v1/keys \ -H "Authorization: Bearer sk_test_…" \ -H "Content-Type: application/json" \ -d '{"endUserId":"user_123","bundle":"default"}' curl https://gw.ourseams.com/v1/chat/completions \ -H "Authorization: Bearer ak_…" \ -H "Content-Type: application/json" \ -d '{"model":"acme/smart","messages":[{"role":"user","content":"hello"}]}' ``` --- source: https://ourseams.com/quickstart/typescript # TypeScript Point the base URL, mint a key per end user, call with that key. ``` See the page for the full Node fetch example. ``` --- source: https://ourseams.com/quickstart/python # Python Point the base URL, mint a key per end user, call with that key. ``` See the page for the full requests example. ``` --- source: https://ourseams.com/start # Sign-up is not open yet. The console that mints your first key is not deployed. What is running today: - https://portal.ourseams.com — the end-user portal, in the tenant's own brand. Usage is metered from real rows; Spending and Billing are still fixtures. - https://api.ourseams.com/v1/openapi.json — the control plane's own document, generated from the routes it serves. Reads answer from Postgres, and minting a key works in test mode; the writes that are not built answer 501 naming the issue that will build them. - https://ourseams.com/llms.txt — the short index for an agent. - https://ourseams.com/llms-full.txt — every page here as one flat file. No request reaches a real model yet: the gateway is not deployed.