Skip to main content

Changelog

v1.7.1 (2026-09-05)

The theme of this release is being told what you actually paid. Where you pay by card, the payment provider now works out any tax that applies and issues you a real invoice for that payment — and both the figure and the link travel back to the row you are looking at. The document this platform issues you is now called a statement throughout the portal, which is what lets the provider's invoice mean something rather than compete with it.

Your wallet is always credited the amount you chose

This is the invariant the whole release protects. A $100.00 top-up credits $100.00 to your wallet whatever your card was charged. Tax never becomes spendable balance, on a top-up or on a statement payment. The presets and the amount you type in Add funds are the credit you are buying, not the card charge.

Your card charge can therefore be higher than the amount you picked. The transaction row says so — +$100.00 with Paid $120.00 (incl. $20.00 tax) · Invoice ↗ under it — and the provider's invoice is one click away. See What a card payment actually cost.

"Invoice" now means the payment provider's document, and nothing else

The document this platform issues you is called a statement: it records the usage in a period and the amounts it comes to. It is a record we issue, not a tax invoice. Where you pay by card, the invoice for that payment is issued by the payment provider and carries any tax.

This is a wording change only. Every API path, field name and scope id is unchanged — /api/v1/billing/documents/invoices/…, billing:read_invoices and every invoice_* field keep their names, and no integration needs to change. What moved is the label on the screen: Statements & transactions, the Statements tab, Statement issued, Period statement, Pay statement.

Your billing address needs a city and a postal code

A tax rate is sourced from an address, so city and postal code are now required in every country, and a State / Province code is required for the United States, Canada, Australia and India. The state field takes the bare subdivision code — NY, not US-NY.

A billing profile that was complete before this release is still complete; nobody becomes unable to pay because a new field appeared. You will be asked for the missing parts the next time you edit the form. See Billing details.

A retiring model is now marked on its own page too

/models/{id} previously carried no retirement marking at all, so a deep link or a search result could land you on a model that was on its way out without saying so. It now carries the same Retiring chip, date and successor as the catalog and the Playground picker. Nothing about the retirement itself changed. See Retiring Models.

v1.7.0 (2026-09-03)

The theme of this release is being told before something changes. A model that is going away now announces itself in the portal, in your inbox and in the HTTP responses your code already receives — and it keeps serving normally right up to the date it names. Your platform's agreements, where your operator publishes any, appear as checkboxes you tick and as a dated record you can read back. And a handful of responses that used to be indistinguishable from a bug now say what actually happened.

A retired model answers 410 Gone, not 404

When your operator retires a model, the retirement is published as two dates — an announcement and a retirement — plus either a successor model or a short note saying there deliberately is none. The model serves every request exactly as before until its retirement moment. Nothing is throttled, refused or priced differently in between.

From the retirement instant, the model drops out of GET /v1/models and every request naming it is answered 410 Gone with "code": "model_sunset" and the successor named in the reply — on streaming and non-streaming requests alike, and a live transcription session naming it is refused at admission. Branch on error.code, not on the sentence. 410 is not 404: 404 means "no such model" and sends a developer hunting for a typo that is not there, while 410 means "it existed, it is gone, and here is what to use instead" — actionable, never retryable. See Model Deprecation.

Your requests start carrying three new response headers

A model that has been announced sends Deprecation (RFC 9745), Sunset (RFC 8594) once a date is fixed, and a Link header pointing at the deprecation policy and, where there is one, at the successor. They ride every endpoint that resolves a model, they are written before the first byte of a server-sent-event stream so nothing is ever injected into the stream itself, and an unknown response header is ignored by every SDK — so this cannot break a client that is not looking for it.

The two timestamp formats differ on purpose and are easy to mistake for each other: Deprecation is @ followed by unix seconds, Sunset is an HTTP date string. Parse each in its own format rather than trying one and falling back. A Deprecation header on a response you are already receiving is the earliest, cheapest possible warning, and it needs no polling.

Test for the key, not for a truthy value

The retirement fields and the new region field are omitted entirely when they do not apply — never sent as null, never as an empty string. A null meaning "not being retired" and a null meaning "being retired, no date fixed yet" would be two facts and one value, so neither is ever sent. deprecated_at without sunset_at is a legitimate, expected state: announced, date not yet fixed, still serving, never refused, and no countdown shown anywhere.

Added

  • Retiring models are marked in the portal, with the date and the successor. An amber Retiring chip sits beside the status pill rather than in place of it — the pill still reads Running, because a retiring model keeps serving — on both catalog views and in the Playground picker, on the palette row and on the selected-model card, so a model is chosen with its deadline in view. The countdown is rounded down, so 30 hours left reads 1 day left, never 2, and the date is always shown in UTC. Where no retirement date has been set yet, the catalog says so and shows no countdown at all. See Retiring Models.
  • A banner, but only if it is about you. When your organization has actually called a retiring model in the last 30 days, a banner at the top of the Models page names each affected model, its date and its successor. Organizations that have never called the model do not see it: a banner everyone sees is a banner nobody reads.
  • Emails at up to five points, where your operator has enabled them: on announcement, then 30 days, 7 days and 1 day before the date, and once more on the retirement day. Each notice names the model, the date, the successor or your operator's note, and — where the figures are available — your own request and token volume on that model. Only the most urgent notice due is sent, so you never get two at once, and nothing is sent until a retirement date exists.
  • Five retirement fields on the API. GET /v1/models and GET /v1/models/{model_id} carry deprecated_at, sunset_at, replacement_model_id, replacement_model_name and replacement_note where they apply. Read replacement_model_name — it is the string you would put in model, and it is resolved for you, so there is no lookup to do. Do not hardcode the retirement date: it can move, usually later, and the change is published on the same fields and the same headers. See Retirement fields in the API.
  • Models can say where they are served from. Where your operator has recorded it, a model carries a region: one uppercase ISO 3166-1 alpha-2 code naming the jurisdiction it runs in, such as TR, DE or US, with EU available for a model an operator can only place inside the Union. It is a single value, not a list, and it is optional — a model with no recorded region carries no region key at all. In the portal it appears in the Playground model picker and on the selected-model card as a flag and the code; a model with no region shows nothing there, no placeholder and no dash. See Serving Region.
  • Agreements you tick, and a record of what you agreed to. Where your operator publishes a privacy policy, terms of service or a marketing opt-in, they appear as checkboxes on the screens that create your account — accepting an invitation, and onboarding after a Google or GitHub sign-in. Required ones carry a red asterisk and block the submit until ticked; optional ones are marked, and leaving one unticked is recorded as a decision, not an omission. A missing box blocks the submit before anything is sent, so nothing you typed is lost and an invitation link is not consumed — fix the boxes and submit the same form again. Links in the wording open in a new tab or in a dialog over the form; neither ticks the box for you and neither disturbs what you have typed. See Legal Agreements.
  • If your operator publishes no agreements, none of this appears anywhere. The sign-up screens, the profile page and the sign-in flow are exactly as documented elsewhere, with no extra boxes and no extra step.
  • Your consent record, on your profile. A Legal & consents section lists every decision you have made, newest first, with the wording, the version, the date and the screen it was collected from. The record is append-only: changing your mind adds an entry and never edits or removes the one before it, which is why a document you have gone back and forth on shows an Earlier decisions list beneath its current state. Accepted, Declined and Withdrawn are three different facts and are labelled as three. An agreement your operator has since retired still appears with the decisions you made about it — the record outlives the document. See Legal & consents.
  • Optional agreements can be turned on and off from your profile. Flipping the toggle appends a new entry; the earlier entries keep their original timestamps. Required agreements show a Required chip and no control — they are a condition of holding the account, so ending one is an account-closure conversation with your operator rather than a switch on a page.
  • A re-consent screen, when the wording actually changes. If your operator republishes an agreement and asks existing users to re-accept it, you are stopped on your next page by a single screen carrying every outstanding agreement at once. Accept and continue records them all and returns you to where you were heading. There is no "skip" and no "later" — typing a portal URL directly lands you back on it — but Sign out instead is always available, so you are never trapped. An optional agreement never blocks you; it shows up on your profile instead. And it never comes before onboarding: a brand-new single sign-on account that owes both finishes onboarding first.
  • You can see whether an invitation email actually went out. Each pending invitation in your organization now carries a second badge beside its Pending or Expired state — Sending, Sent, Delayed or Not delivered — with a short sentence saying what to do, and the time of the last attempt on hover. Delayed means the platform is still trying and the invitation link stays valid. A resend now confirms with "Invitation queued" rather than claiming delivery, and the badge updates itself a moment later without a page reload. GET /api/v1/tenant-admin/invites carries the same information as a delivery object. See Invitation Delivery State.
  • A standing notice under the Playground workspace: "Models can make mistakes. Verify important information." It appears on every Playground surface — chat, image, speech, transcription and live microphone — and stays put across model and mode changes. It states a permanent property of model output rather than reporting a problem, so it is quieter than the notices the Playground raises when something has actually gone wrong.

Changed

  • None of these badges is about the recipient's mailbox. The delivery states describe the platform's own attempt to send. Nothing here tells you an address was wrong or that a mailbox rejected anything — the platform does not track bounces. The most common Not delivered reason is about the invitation going stale (expired, accepted, cancelled, or replaced by a newer resend that rotated the token), and the right response is to create a new invitation, not to check the address.
  • GET /api/v1/tenant-admin/invites is the only place delivery is reported. Creating or resending an invitation deliberately returns without a delivery field, because the email has only just been queued and answering delivery: null would assert that no email exists. Read the list back if your integration cares.
  • PDF is now the only document format, on every model. Documents are converted to page images before they are forwarded, and that is true whichever engine serves the model — so vision is the single capability that answers both "can this model read an image" and "can this model take an attachment". Two refusals follow, and both now behave identically everywhere: a model without vision answers 400 naming that, and a non-PDF file part answers 400 asking you to convert it. Models served by an external provider previously had their file parts forwarded untouched, so any type was accepted here and refused upstream in the provider's words rather than the platform's; the Playground's upload menu no longer advertises document types the platform cannot send. Images are unaffected. See Document attachments.
  • A request carrying documents is size-checked twice — once on the body you sent and once after the pages are converted — because page images are considerably larger than the PDF they came from. A document that passes the first check can now fail the second with 413, and the reported figure is the total of every inline attachment, to one decimal place.
  • Back-pressure from the account and organization API is a 503, not a 500. Those endpoints answer 503 with "type": "service_unavailable" and Retry-After: 1 when the service is at capacity or cannot reach its database, on every route — previously only one internal path did this and everything else answered 500 server_error, which was indistinguishable from a defect. Retry it: the request itself is fine and usually succeeds on the next attempt. Two cases matter more than the rest: signing in used to answer 401 on a capacity blip and spend a failed-login attempt toward account lockout, and refreshing a session used to answer 401, which reads as "your session ended" and logs you out. Both now say what is actually happening. A 500 from these endpoints now means something genuinely went wrong with the request. See Error Handling.
  • Documents finally work against externally hosted models. They were previously forwarded in a shape the provider does not accept, so every document request to such a model failed at the provider while images to the same model worked.
  • Your models stop disappearing from the catalog under load. The platform resolved each model's deployment state with an unbounded fan-out, and past its own limit those lookups timed out — and a timed-out lookup was read as "this model is not deployed", so the model was dropped from your list. You were served a 200 with a shorter list and a total that agreed with it. A model whose state cannot be resolved now stays in the list marked unknown, and only a definite answer hides one.
  • Phone numbers are held in international form. The field now shows and stores the number as it is dialled from abroad, without the national trunk prefix, because the dial-code chip beside it already supplies the country — a Turkish mobile reads 501 234 56 78, not 0501 234 56 78. A leading trunk digit you type is dropped for you, a leading zero that is genuinely part of the number is kept, and switching country re-formats what you have already typed so a number is never left half-composed from two plans.
  • Audio totals are organization-wide, deliberately. The audio card in My Usage carries an Organization-wide pill. That is a decision, not a missing number: audio requests only began recording which member made them partway through the platform's history and there is no way to work out the earlier ones, so a per-member figure would be partial in a way you could not detect. An organization total has no such hole and is the same number for every role. See Usage.
  • A background job's default time limit is now 25 minutes. Jobs that ran longer were previously being executed twice — the same work running concurrently, and your token-rate and spend counters charged twice for one job. A job that legitimately needs longer now fails cleanly and is recorded as a timeout; a per-request timeout_seconds above the ceiling is clamped rather than rejected. The honest comparison is not "worked before, fails now": that job was silently running twice.
  • The speech endpoint's second, much wider input wall is now published. The OpenAPI schema declares maxLength: 65536 on input — sixteen times the 4,096-code-point cap. It is not a second limit to design around; it lets an absurd body be refused without any work being done on it first. An input above it is refused with the same 400 input_too_long naming the same 4,096 limit that you would get at 5,000 characters — it simply arrives immediately now instead of after the platform has normalized a body it was always going to reject. 4,096 remains the only number to write your splitting logic against. See Text to Speech.

Improved

  • A dead or restarting model fails in about five seconds instead of up to twenty minutes. A single timeout value was being applied to the connection, the read, the write and the pool alike, and with retries on top one request could sit for the better part of an hour holding a slot.
  • Streaming responses have their own budget. Every streaming completion previously inherited a 30-second limit that acted as a hard time-to-first-token deadline, and when it fired the failure was terminal — the response had already started, so the only report was an error inside the stream, and the tokens that had arrived were still billed. The budget is now measured between chunks, so a long generation is never cut off for being long.
  • An over-long speech request is refused immediately. The full text-normalization pipeline used to run on the input before the length was checked, so a very large body spent tens of seconds being processed purely in order to be rejected. The answer is unchanged; it just arrives at once.
  • A momentary capacity problem no longer looks like a broken request. Beyond the 503 change above, requests that would previously have queued for 30 seconds now fail fast and explicitly, and a request whose work had already been recorded no longer reports an error because of a database lock behind it.
  • Password reset and verification emails are retried rather than lost. They are now queued and delivered with backoff instead of being sent inline during your request, so a slow or briefly unavailable mailer no longer turns into a failure you see. Resending a verification email no longer reports a server error when the mail system is simply busy.
  • Invitation emails have their own sending allowance, so ordinary team onboarding no longer runs into a ceiling shared with password resets to the same address.
  • The Playground upload menu tells the truth about what it accepts, and its attach button says why it is unavailable: "This model does not support file attachments".
  • Faster, quieter responses across the board. Document rendering, audio file handling and logging moved off the request path, streaming responses no longer retain their own body in memory, and repeated model lookups during a deployment restart no longer stampede — so latency under load improves broadly even where nothing you call has changed.

v1.6.0 (2026-08-28)

The theme of this release is money you can see before it moves. Your balance is checked and held before a request runs rather than tested against a cached figure afterwards; a plan change tells you what it will cost before you confirm it and what happened after; you can buy a plan with a card and keep that card for renewals; and a postpaid organization can finally read what it owes. Around that: the portal now takes its colours, logo and name from your platform's own configuration, a model that cannot actually be served is refused honestly instead of failing at the provider, and the Billing and Plans pages were rebuilt around one predictable shape.

A prepaid request is now held against your balance before it runs

Admission used to test your balance against a value cached for up to 30 seconds and reserve nothing, so a burst of concurrent requests — or one large request — could be served well past a balance that could not cover it. The platform now prices the request's worst case and holds that amount against your wallet before the request is sent anywhere. If the hold does not fit you get 402 with "type": "insufficient_quota", "code": "insufficient_credits" and a limit_type of wallet_balance, before any tokens are generated.

The worst case is priced from max_tokens, not from the reply you actually get. A request asking for 4,000 output tokens holds 4,000 output tokens' worth even if the model answers in twenty words, so a generous max_tokens on a small balance is now refused where it used to be served. The hold is released the moment the request finishes and you are billed on real usage — nothing is ever charged from the estimate. Transcription, speech and live transcription are covered by the same rule, and insufficient credit on a live transcription session closes it with code 4402 instead of failing mid-stream. An organization on a plan, inside its included allowance, is never refused this way. See Billing and Error Handling.

An unavailable model is refused, not dropped from your catalog

The platform now checks continuously that each externally hosted model is really being served, and refuses one that is not — before the request reaches the provider. Such a model stays in your catalog and stays listed: your grants, your prices and the model id you call are all unchanged. GET /v1/models gains is_serviceabletrue serving, false judged not serving, null unknown or not applicable. Treat null as unknown and never as false. A model that is merely slow is still served. Separately, a 404 from an external provider now reaches you as 503 upstream_unavailable with a Retry-After rather than as a 400, because it means the platform's own record of that model is stale and not that your request was malformed. See Models.

Card features appear only where your operator has switched them on

Buying a plan with a card, saving a card for renewals and paying an invoice by card all depend on your platform operator having configured a payment provider and enabled paid plan purchases. Where they are not enabled, those controls are absent rather than leading to a refusal, and plan changes continue to go through a review request as before.

Added

  • Buy a plan with a card. Where your operator has enabled it, a paid upgrade offers Upgrade instead of Request change and takes you to checkout with a server-calculated amount — the real prorated figure for where you are in your billing period, frozen when the order is created, not the plan's list price. There is no amount field to fill in and nothing is read from the link you arrived on. The checkout states when the order expires, and after payment the return page tells you the change is on its way rather than claiming the plan is already live. A downgrade or cancellation is now labelled Switch plan. See Plans.
  • See what a plan change costs before you confirm it. Both confirm dialogs — switching plan and cancelling one — now carry a money panel: the new plan's monthly price, what is charged when the change takes effect, the credit for the plan you are leaving, the net due now, and the figure that recurs at renewal. Every number comes from the platform, and the quote is worked out when you open the dialog, because the credit for your outgoing plan shrinks as the period runs. If the platform cannot work the cost out it says so and still lets you confirm. Available on its own at GET /api/v1/plan/change-quote.
  • See what happened after a plan change. An approved change shows what it was and when it took effect; a declined one names the plan, states that nothing was charged, and prints the administrator's own written reason; a withdrawn one says so plainly. A five-row Recent plan changes card carries the history. Previously a rejection was completely invisible — the pending banner simply disappeared and nothing replaced it.
  • Keep a card for renewals, and manage it. At checkout you can consent to keep your card so the plan renews itself. The consent statement says what is stored, that the card is charged recurrently, how the amount is arrived at and how to stop it — and it is unticked by default. Note that the payment provider's own hosted page carries a second, mandatory agreement, and its submit button does nothing until that one is ticked too. Billing then gains a Payment methods card where you can list your cards, set a default and remove one; removing your last card warns you and never refuses. The plan card shows your next charge and which card it will be charged to, and an authenticate now banner appears when your bank needs you present for a renewal that cannot complete on its own. See Billing.
  • Renewal emails. You are now told when a renewal was charged, when a card was declined and when the next attempt falls, when your bank needs you to authenticate, when there is no card on file to charge at all, and when a card has been saved. A card top-up now produces a receipt, and a plan activation is announced when the plan is live rather than when the order was placed.
  • A postpaid organization can read what it owes. Billing's current-period card leads with usage delivered that no invoice bills yet, beside invoiced-and-unpaid and the total outstanding, and the accrual covers every uninvoiced period rather than only the current one. A prepaid organization holding unpaid issued invoices gets one line stating the total and pointing at Statements. Any figure the platform cannot work out reads and never $0.00.
  • Your spending appears in your account activity. Money leaving your wallet is now summarised as one line per day, so an account that topped up and then spent no longer shows only the top-up.
  • Invoices record who they are billed to — legal name, tax ID, country, address and invoice email are snapshotted onto the document when it is issued, so correcting your details later never rewrites a document you have already been given. Tax fields are present and read zero: this platform makes no tax determination today, and a blank tax rate means exactly that, not "0%". No amount on any invoice moves.
  • Audio invoice lines carry a unit price. They previously showed a quantity and an amount with the rate left blank. Where more than one rate genuinely applied inside one unit during a period, the line splits so every line carries one rate that really was applied, and the two amounts sum to what the single blended line billed.
  • A budget plan's audio charges are published. GET /api/v1/plan/current now carries totals.audio_cost on a budget plan. Speech holds no allowance, never draws a plan's budget and is billed per request from your wallet, so withholding the figure hid a charge you had already paid.
  • The catalog says whether a paid upgrade can be bought with a card. GET /api/v1/plans gains card_upgrade_enabled, resolved from the same rule the order endpoint applies, so the catalog cannot promise a checkout the order would refuse.
  • Your platform's branding reaches the portal and your mail. Colours, logo — including a dark-mode variant — platform name, tagline, copyright line and the sign-in and dashboard backgrounds are configuration now rather than something baked into a build, and the emails you receive are branded from the same configuration as the portal, so the two can no longer disagree. Text placed on a branded surface is chosen for contrast rather than assumed to be white.

Changed

  • The Plans page is a ladder, not a wide table. Plans are rows with five fixed columns, so the page no longer scrolls sideways and no longer pushes plans off-screen as the catalogue grows — and it no longer renders mostly empty cells. Every "nothing here" case is now a sentence, each expanded row names the models it does not cover, and side-by-side reading returns as an opt-in comparison tray on two or three plans. The whole page is keyboard-operable.
  • The Billing page has one shape for every account. It previously took roughly eight different forms and deleted whole regions when a figure came back empty, so two customers on the same platform could not compare what they were looking at. There are now four regions, always present, always in this order: what you owe → what you have → what you are using → what you have been charged. Your account state changes what is inside a region, never whether the region exists, and a surface your operator has not enabled now says so rather than silently vanishing.
  • Your current plan is read from your account, not from the public catalog. A privately assigned, negotiated or contracted plan is not in the public catalog, and the page used to fall through to the default — so such customers were told their plan was the free pay-as-you-go one, complete with a "Current plan" badge on a column they were not on. A private plan is now named and priced in the header with a note that it is not in the comparison, and a contracted plan is named with a note that the period is billed under the contract.
  • A plan that grants an allowance shows it, whatever it costs. The quota surface used to appear only if the plan charged a fee, so a zero-fee plan with a real allowance showed one total and a number-free sentence — the exact shape used for pilots, trials and negotiated arrangements.
  • A mid-cycle upgrade is prorated on both sides. The plan you leave was credited pro rata while the plan you join was charged in full, so upgrading on the last day of a cycle cost a whole month for one day of service. Both sides are now charged for the part of the cycle that remains. The invoice line states the basis — the factor, the full monthly price and the cycle it was computed over — so quantity x unit price = amount reads back the whole calculation. A change landing exactly on a cycle boundary is charged the full fee, unchanged.
  • Cancelling a payment now closes it at the payment provider too, not only in the platform's own record. The page tells you that nothing further can be charged only once that has been confirmed; otherwise it says nothing has been charged and asks you not to return to the abandoned page.
  • A card-paid upgrade names the right next-charge date. Paying for an upgrade opens a new billing period immediately, but checkout was printing the end date of the period you were leaving, so the two screens disagreed by weeks. Both now take the date and the amount from the same quote.
  • A plan bought by card is paid by that card alone. The payment is now recorded against the plan fee before your wallet is consulted, so a prepaid organization's balance is left where it was.
  • A coupon code is matched without regard to capitalisation, and surrounding whitespace is ignored. A code that could never be redeemed — one whose validity has already ended, or one scoped to an organization that does not exist — is now refused when it is created rather than accepted and silently unusable.
  • The limits your administrator set for you are the limits enforced. A per-organization or per-user limit above your plan's tier was being accepted, stored and then quietly clamped back down to the plan value on every read. If a higher limit was agreed for you, you now get it.
  • An order for a plan that is sold through your account team is refused with a clear conflict rather than being accepted as a self-service purchase.
  • Zero-total statements no longer generate an email. Every in-quota plan month closed a document totalling 0.00 and mailed it.

Improved

  • The Playground plays every clip through one player. File previews and voice previews used the browser's own audio control, which looks different in every browser; they now use the portal's player, with a waveform of your own audio where the file is small enough to decode and a plain progress track otherwise. An upload your browser cannot play can still be transcribed, and says so. The waveform also stays a waveform on a wide screen instead of collapsing into a dotted line.
  • Speech output formats are visible while you choose. All formats and their one-line trade-offs are on screen rather than hidden in a menu, and the generated-speech area now names its own state — empty, generating, ready or failed — under a fixed height, so the panel no longer jumps as a run starts and finishes.
  • The microphone is explained before the browser asks for it, and a permanently blocked microphone is now detected and named. Previously "blocked" and "never asked" looked identical from inside the page: no prompt appeared and the button simply did nothing. You are now told where the switch is, and that uploading a file still works. Fixing the permission in your browser settings takes effect without reloading the page.
  • Usage charts are drawn consistently. Every line is one weight, a line no longer thickens and thins depending on its direction, and a long range no longer draws so many point markers that the line reads as dashed.
  • The sign-in page appears immediately. It used to render a full-screen spinner until the browser had downloaded and started the whole application, and the sign-in options are now resolved before the page is sent. The Google and GitHub buttons also carry each provider's real mark.
  • Explanatory hints can actually be read. The hint panel opened on hover and closed the moment the pointer moved toward it, so its text could not be reached with a mouse at all. It now stays open, can be clicked to latch, survives scrolling and returns focus where it came from.
  • The create-key dialog no longer resizes under your pointer when you switch between key types, and the profile edit form no longer stretches into empty space. Clicking Link on a connected account no longer slides the button out from under the cursor that just pressed it.
  • A workbook you export carries your platform's name in its document properties rather than a fixed one.

v1.5.0 (2026-08-19)

The headline of this release is that you can now pay by card. Alongside it: signing in with Google or GitHub, signing up without waiting for an invitation, per-key analytics, named voices for text to speech, and a large batch of corrections to what the platform tells you when it refuses a request.

A spend stop is now a 402, not a 429

Four money ceilings — the daily cost ceiling, the per-user daily cost ceiling, your API key's spend cap and the monthly cost ceiling — used to answer 429 rate_limit_error. They now answer 402 insufficient_quota, matching your credit limit and your organization spending cap, which already did. An OpenAI-compatible SDK maps 429 to a rate-limit exception and does not map 402, so code that caught and backed off on a spend stop will now see an unhandled error. Request, token and concurrency limits are unaffected and still answer 429. Each refusal now names the amount and a remedy you can actually perform. See Error Handling.

Card payment is a feature your platform operator switches on

If your operator has not configured a payment provider, card top-up and "Pay by card" simply do not appear anywhere in the portal. That is a deliberate configuration, not a fault. Coupons continue to work, and are the way credit reaches your wallet on such a platform.

Added

  • Pay by card: Top up your wallet or settle an invoice with a card, from the Billing page. Add funds opens in front of the balance it changes, states the amount range the platform accepts, and shows what your balance will be afterwards. You can also pay for a plan change the same way. Card details are entered on the payment provider's own hosted page after a full redirect — the portal loads no third-party payment script and has no card field of its own.
  • See your payments: In-flight, declined, failed and abandoned payments are now visible rather than silently missing, each with its own state. Previously a payment attempt existed only for as long as the browser tab that started it. Reloading the confirmation page after a successful payment no longer tells you the payment failed, and Try again after a declined invoice payment retries that invoice, not a blank wallet top-up.
  • Refunds: Money is returned to the card it was paid from, bounded by what you have not already spent. The refundable figure the platform shows you is now the figure a refund will actually accept — it is rounded down and excludes usage you have incurred but that has not yet settled.
  • Billing details on your organization: Legal name, country, address and invoice email, recorded once and reused for every payment. Tax ID is optional. See Organization.
  • Sign in with Google or GitHub: Where your platform administrator has enabled it, single sign-on appears above the password form, and linked accounts are managed from your Profile. A provider can only be linked when it confirms the same verified email address as your account, and you cannot unlink your last way of signing in. See Signing In.
  • Sign up without an invitation: Where self-serve signup is switched on, a Sign up link on the sign-in page starts an email-verified registration, and you can name your organization on the way in. When it is switched off the link is absent rather than leading to a refusal.
  • Per-API-key analytics: Every API key row gains an Analytics action opening a per-key version of the Usage page — the same metrics, trends, model breakdown and recent activity, scoped to one credential. Organization admins and owners can read any key; other members see their own. You can also filter usage history by key. See API Keys.
  • Named voices for text to speech: A model can publish a catalog of preset voices, selectable by name. A voice is only advertised once it is live on every server behind the model, so a voice you can pick is a voice that will work. Voices can also be made available to your organization specifically rather than to everyone using a shared model.
  • Model logos: The catalog, model detail, playground picker and search palette show each model's real logo instead of a generic type icon, with the old icon kept as the fallback. The catalog API gains logo_url, logo_source, logo_updated_at and a brand block.
  • Speech translation and language hints: /v1/audio/translations is now gated on the model actually declaring the capability, and a model can publish the languages it supports so the Playground offers them as a list rather than a free-text box.
  • More control over transcription: seed, top_p, top_k and min_p are forwarded to the model on transcriptions, and seed on translations, matching what the engine documents. A field the endpoint does not support is now rejected with a clear 400 naming it, instead of being silently discarded behind a successful response.
  • A real audio player in the Playground: Play/pause, seek, mute, a clock and a waveform decoded from the audio you actually received. Voice and output-format pickers were rebuilt. The speech surface also gains a glossary field for brand and product names — the single largest accuracy lever for proper nouns — a temperature control, rendered segment timestamps, and a streaming toggle for text to speech.
  • A microphone picker for live transcription, plus a guard that ends a session and tells you when your selected input is producing digital silence — the virtual-audio-device trap where you stream, and are billed for, nothing at all.
  • Per-day detail on the Dashboard: Activity cells open a panel with that day's request count and input/output/total token split, reachable by keyboard and touch rather than only by hovering.

Changed

  • Logging out ends only the device you are on. Your other browsers and devices stay signed in; use Sign out everywhere on your Profile page to end them all. Revoking a session now takes effect on its very next request, and session revocations appear in your own security activity.
  • One email, one account, platform-wide. An address identifies exactly one account across the platform. Inviting an address that already belongs to another organization now returns the ordinary success response and writes nothing, rather than confirming that the address is taken. If you already have an account, an invitation to a different organization will not create a second one.
  • Accepting an invitation now signs you straight in instead of creating your account and then dropping you back at the login page.
  • A background request accepts exactly the same body as a synchronous one. Multimodal content parts and PDF attachments now work with background: true, and the developer role is accepted. Streaming responses from background jobs now carry usage, system_fingerprint and logprobs instead of dropping them, and a failed job reports a machine-readable error code.
  • Private models are visible only to the organizations that hold them. Retrieving a model by id now answers "not found" unless your organization has been granted it. Previously a private model belonging to another organization could be read by name, along with its owner's identifier. The popular models list is affected the same way and now returns fewer entries: it used to show every caller the most recently created models platform-wide, including other organizations' private and deleted ones.
  • GET /api/v1/rate-limits reports your real limits. It previously ignored the caller and returned platform defaults — every number was wrong. Per-API-key overrides are still not reflected there.
  • POST /api/v1/auth/accept-invite no longer requires email, which the invite token already carries. Sending it is still accepted.
  • GET /api/v1/usage no longer advertises start_date / end_date, which it silently ignored. The endpoints that do honour a window now document the window, the span cap and the timezone default.
  • Top-up credit means card money only. Credit the platform granted you is reported separately, so the top-up figure can no longer read higher than what you were actually charged.
  • Your money feed is classified by type, not by sign, and now shows the whole picture. Payments recorded by support, discounts and waivers applied to you, and payment reversals all appear in your account activity, where previously only money coming in was listed and operator corrections were visible only by opening each invoice. Your in-period usage spend appears as one line per day. A reversed payment restores debt and is shown as a charge; a discount is shown as a credit. Several transaction types that previously rendered as raw enum names now have proper labels.
  • A prepaid period that closed against your balance no longer leaves an invoice standing as though nothing was paid.
  • Money held against an open card dispute is shown as held rather than silently spendable, and the rest of your balance is unaffected.
  • Billing stays reachable if your organization is suspended, so you can review your statements and pay what is owed. Everything else, including inference, is refused. You are now also emailed when your organization is suspended — with the reason and what to do about it — and again when it is reactivated.
  • The metric formerly labelled "Cached Tokens" is now "Cache Read" across the portal. It is a different metric from the cache-hit rate, which is unchanged.
  • Usage charts are bucketed on your local day, not on UTC. Daily, weekly and monthly points now respect your timezone across daylight-saving transitions, so traffic just before local midnight is charted on the day it happened. Hourly points stay on UTC hours. This also fixes two defects for anyone at UTC+0 or west: the current local day was missing from every preset range, and the days that did chart were labelled one day early.
  • The per-key analytics endpoint is reachable with an API key carrying usage:read_report. A key created from the legacy usage:read grouping already has it, so nothing needs re-issuing.
  • Low-balance emails are sized to how much you actually spend — by default seven days of your own recent average — instead of a flat threshold, are not sent before you have used anything, and state the figure the alert was based on. Expired credit is reported as the amount actually retired, never rounded up against you.

Improved

  • Refusals name a remedy you actually have. A spend-cap refusal now states the amounts and points at your own organization spending cap instead of telling you to contact support, which has no lever to raise it. Raising an API-key spend cap lifts the same-day block immediately rather than at midnight UTC.
  • Provider errors no longer reach you raw. An upstream failure is normalised into the platform's own error envelope, another vendor's branding, account balance and payment links are stripped from responses, and a failed stream can no longer arrive as a 200.
  • A suspended organization is told it is suspended, instead of being told its API key expired.
  • An internal dependency outage does not become a blanket outage. A fault in a cost or pricing lookup is logged and counted rather than turned into a 503 for all inference.
  • A cancelled payment says so immediately. Backing out of the payment page used to leave you watching a confirmation spinner for two minutes and then a vague "may still complete"; you are now told straight away that nothing was charged. A declined card is reported as declined rather than looking the same as a payment you never started.
  • Rejected invitations say why. Accepting an invitation now shows the real reason a submission was refused, and name rules are checked inline before you submit rather than after. Invitation emails state the correct expiry, and a delivery retry cannot send you a second invitation.
  • Transactional email is more reliable. A message the platform could not deliver on the first attempt is retained and retried rather than dropped, and a retry cannot duplicate it. If you sign up on your own you now receive a proper account-completion email instead of one saying you were invited to join an organization.
  • A job interrupted by an infrastructure failure is retried rather than lost, and is never charged twice.
  • Sign-on refusals are specific. Each way a Google or GitHub link can fail now has its own explanation, including the case where the provider will not confirm a verified address — previously several of them showed only "please try again".
  • Your profile returns your name and role, which previously came back empty.
  • New voices are usable straight away after an operator adds one, instead of waiting up to an hour for a catalog cache to expire.
  • Model logos, dates and large numbers render consistently across the portal, and the selected date range on Usage is announced to screen readers rather than only being painted.

v1.4.0 (2026-08-03)

Two big things in this release: your account is now billed the way a normal business account is billed, and the API learned to listen and speak.

How your account is billed now

Your organization is billed in arrears. You no longer need a prepaid balance sitting in your wallet before you can make a request; you use the platform, and the usage is accrued against your account. Unless a specific credit limit has been agreed for your organization, there is no ceiling on the account beyond the platform's own daily protections. Coupons and top-ups still work exactly as before, and still appear under Transactions on the Billing page.

Invoices are not issued on a schedule yet

Billing periods now run from the 1st of the month to the 1st of the next, and your current period is always visible on the Billing page. Invoices are not yet issued automatically, so the Invoices tab will be empty. Your accrued usage, your current charges and your transactions are all live and accurate in the meantime.

Added

  • Speech-to-text transcription: New OpenAI-compatible /v1/audio/transcriptions and /v1/audio/translations endpoints turn recordings into text or English. Transcriptions come back as json, plain text, timed verbose_json, or ready-to-use srt / vtt subtitles; translations come back as json, plain text or verbose_json. See the Speech to Text guide.
  • Text to speech: POST /v1/audio/speech turns text into audio in six formats: mp3, opus, aac, flac, wav and pcm, and honours stream so a long synthesis arrives as it is produced. You are billed on the characters you send, priced per million characters; the length of the audio you get back does not change the price. See the Text to Speech guide.
  • Live transcription: Stream microphone or telephony audio to /v1/realtime over a WebSocket and read the transcript as the speaker talks. The browser gets a short-lived connection token rather than your real API key. See the Realtime Transcription guide.
  • Streaming transcripts: Set stream=true to receive a transcript over Server-Sent Events as it is produced, framed the same way as the rest of the platform's streaming API and closed with data: [DONE].
  • Audio in the Playground: Upload a file or record from your microphone in the Client Portal Playground, choose the output format, and read the transcript without writing any code. The Playground also gained a text-to-speech surface with voice preview, and a live-microphone mode for realtime transcription. See Playground Audio.
  • Audio usage and pricing: The Usage page gains an Audio usage section with requests, processed audio time, and charges. Speech-to-text is measured per second of input audio and priced per minute, with rates shown on the model detail page.
  • inference:audio scope: A granular API key scope for the audio endpoints. Older keys that carry a broad scope (full access, or general inference) already cover audio. A key you created by picking capabilities one by one does not, until you add inference:audio to it, which you can do without rotating the key. See API Keys.
  • Browse and order plans yourself: A Plans page compares the available plans side by side, with a token-based / consumption-based toggle, and lets owners and admins order a plan without going through support. Accounts on a platform-managed contract still change plans through their account manager. Downgrades and cancellations are approved automatically and take effect at the start of your next billing period; only upgrades wait for a decision. An auto-approved change is still yours to withdraw before it applies.
  • Set your own spending cap: Owners and admins can cap what the whole organization spends in a billing period, from the Billing page. Requests above the cap are refused; your prices are unaffected. See Cost Limits.
  • See what your overage actually costs: Usage beyond your plan's allowance is now broken down per model, priced at each model's own rate rather than at the group's highest rate, with a forecast of where the period is heading while you are in overage.
  • Negotiated prices are visible: If a price has been agreed for your organization, the model catalog shows it beside the list price it replaced, so you can see what you are actually paying.
  • Welcome credit on invitations: An invitation now tells you about the signup credit before you accept, and the credit is granted when you complete registration.
  • Freeze the animated background: A control in the header stops background motion. The choice is remembered per device.

Changed

  • Billing cycles are gone. The /api/v1/billing/current, /cycles, /summary and /invoices endpoints have been withdrawn. Invoices and your money feed are now read from /api/v1/billing/documents/.... See Billing.
  • Money moved to Billing, volume stayed on Usage. The Usage page is now purely about how much you used, broken down by modality with audio first-class; everything about what it costs lives on Billing. Both pages, and the Dashboard, were rebuilt around this split.
  • Error types on money refusals: A 402 for a spend problem now carries "type": "insufficient_quota", and a new no_credit_line code covers an account with no credit extended to it. Refusals from a personal daily limit or an API-key spend cap remain 429. See Error Handling.
  • Token-per-minute limits are enforced over a true sliding window, so a burst can no longer spend two minutes' allowance across a single minute boundary. The x-ratelimit-* headers now report when capacity actually returns, on successful responses and on 429 alike, and the limit's unit no longer changes on a 429. See Rate Limiting.
  • Audio billing units are stated precisely: speech-to-text is metered per second of input audio, and text to speech is metered on the characters of the text you send and priced per million of them.
  • Corrections to an issued invoice appear as their own transactions against the invoice rather than silently changing the document you were given, so an invoice you have already received never changes underneath you.

Improved

  • Long-audio accuracy: Long recordings are handled in a single request, with the transcript assembled so wording and subtitle timings stay aligned with the original recording.
  • Clearer audio limits: Files beyond what a single request can transcribe are reported immediately with an actionable message instead of running to the request deadline.
  • Truncated replies say so: The Playground now labels a reply that stopped at the Max Tokens limit, was cut by a content filter, or ended abnormally, instead of presenting it as complete.
  • A faster model picker: The Playground model dropdown was replaced by a searchable command palette, and chat, image and audio now share one Playground route.
  • Streaming keeps working in a background tab: Switching tabs mid-response no longer stalls the stream.
  • Honest errors when the platform is having a problem: An authentication service outage is reported as an outage instead of telling you your API key is bad, and a Retry-After is passed through to you rather than dropped.
  • Clearer billing copy throughout: The wallet's two numbers can no longer disagree, a blocked account is told it is blocked, an issued invoice is no longer shown as a wallet credit, a plan with no bundled usage says so instead of showing an empty meter, and a spending cap is not attributed to you when you never set one.
  • A portal that fits your screen: The billing and portal layouts no longer scroll sideways on narrow phones, and dialogs no longer clip inside their cards.

v1.2.8 (2026-07-14)

Added

  • Cache savings on your usage view: Usage now shows Cached Tokens and Cache Savings, so you can see how much automatic prompt caching reduces your costs. A per-model Cached column is included in the usage breakdown.
  • Country-aware phone number input: Phone fields now include a searchable country and flag picker with as-you-type formatting and validation, so numbers are entered correctly without typing the country code by hand.

Improved

  • Faster date-range selection: The usage date-range picker now offers quick ranges: a "Last N" builder (minutes through years) plus one-click fixed ranges, and a refined custom range with start/end date and time.

v1.2.7 (2026-07-03)

Added

  • Redesigned API key creation: Create API keys with selectable key types and granular, per-capability scopes, plus improved controls for managing your keys.
  • Expanded API scopes: More granular public API scopes for finer-grained access control.
  • CSV export: Export buttons now offer CSV alongside Excel across the portal.
  • Unified date picker: A shared date picker with manual entry and a theme-aware time picker across usage views.

Improved

  • Timezone-aware usage views: Usage views align to exact calendar ranges and fall back to your browser's timezone when your profile timezone isn't set.
  • Clearer usage charts: Chart tooltips now line up precisely with the hovered data point.
  • More reliable inference: Long-running requests are handled more reliably.
  • Enhanced security hardening: Strengthened HTTP response handling across the platform.

v1.2.6 (2026-06-23)

Improved

  • The sign-in screen logo now adapts to light and dark themes.
  • Clearer, region-neutral example text when naming an API key.

v1.2.5 (2026-06-22)

Improved

  • Longer usage history retention, so your usage and billing reports stay available for extended periods.
  • Improved platform stability under heavy traffic.

v1.2.4 (2026-06-15)

Improved

  • More reliable invitation delivery: invites are queued and delivered through a restart-safe dispatcher, so they aren't lost if a service restarts.
  • Steadier performance during traffic spikes thanks to non-blocking health checks and hardened connection handling.

v1.2.3 (2026-06-03)

Improved

  • Reasoning models in the playground now apply your thinking/reasoning preference correctly whether it's turned on or off.
  • Model configuration changes take effect immediately, without waiting for a cache to expire.

v1.2.1 (2026-06-03)

Added

  • Live password requirements checklist on sign-up and password change screens: each rule turns green as you type.

Improved

  • Dashboard topbar now respects the name from your profile.
  • Usage chart trends now compare against the previous matching period so you can see whether usage is up or down at a glance.
  • Usage reporting is fresher and more accurate; today's activity now appears in your usage views within minutes.
  • Clearer, consistent error messages when a model does not support background jobs.
  • More accurate health-state handling: brief blips no longer trigger the maintenance page, and the maintenance timeout is now operator-tunable.
  • Profile password form is easier to follow: single-column layout with eye icons on every password field.
  • Translation fix on Billing Details for the organization name label.

v1.2.0 (2026-06-02)

Added

  • API key scope constraints: When creating or editing an API key you can now restrict which models the key can call, which IP addresses or CIDR ranges may use it, and set a daily spend cap in USD. Requests that violate any constraint return a clear error.
  • Scope badges on API keys: The API Keys page now shows badges on each row indicating which constraints are active (model allow-list, IP allow-list, spend cap), so it's obvious at a glance how each key is restricted.
  • Date presets for API key expiration: Quick-select pills (30 days, 90 days, 1 year, no expiry) replace manual date entry.
  • Active sessions: The Profile page lists your active sessions across devices with last-used and IP info. You can sign out of any individual session or all sessions at once.
  • Change password from Profile: A dedicated Change Password section now lives in your Profile.
  • Live password requirements checklist: Forms that ask for a new password (sign up, reset, change) display the requirements as a checklist that turns green as you meet each rule.
  • Cancel and resume in the Playground: You can now cancel a streaming response in mid-flight and the partial output is preserved. Edits and regenerations from prior user messages also work.
  • Last sign-in and recent activity: The Profile page now shows your last successful sign-in time and recent activity events.

Improved

  • Billing Details on Usage page: The detail card now shows your Organization name instead of a truncated Tenant ID, clearer at a glance for billing reviews.
  • Account lockout message: After repeated failed sign-in attempts the lockout message is now a single clear sentence ("Your account is temporarily locked. Please try again later.") without raw seconds-until-retry text.
  • Inviting hardening: Resending an invitation respects a short cooldown, refuses expired invitations, and the new email explicitly notes that any earlier invitation link is no longer valid.
  • Streaming UX: The Playground no longer auto-scrolls during streaming, and the chat content is clipped inside the rounded card border.
  • Cmd+K search modal correctness: The search dialog now opens above sticky bars and dims the entire viewport (not just the page body) for clear focus.
  • Mobile theme toggle restored in the topbar.
  • API key expiry badge shows the real remaining days ("1 day", "3 days", "7 days") rather than a fixed label.
  • Excel exports hardened: Exports of usage and analytics escape leading =, +, -, @ to prevent CSV-formula injection if the file is opened in spreadsheets.
  • Real-time streaming for cancelled requests: If you abort a chat completion mid-stream, the partial response is preserved in the Playground and usage is correctly billed for the cancelled portion only.

Fixed

  • API error responses now consistently use {"error": {"message": "...", "type": "..."}}, including 429 rate-limit errors. SDKs and scripts reading error.message no longer have to handle both string and object shapes.
  • Profile session controls now read "Sign out" instead of the confusing "Revoke".
  • Sign-in error rendering: structured error objects from the backend now render as readable messages instead of [object Object].
  • Playground respects the model slug for code examples and corrects login error parsing for non-{detail: string} responses.

Security

  • X-Powered-By header disabled and X-XSS-Protection (deprecated) removed; Content-Security-Policy added across the Client Portal and Landing Portal.
  • Login forms no longer reveal whether an email exists by hashing in constant time and rate-limiting forgot-password attempts.

v1.1.2 (2026-04-16)

Improved

  • API keys are user-owned: Each API key now belongs to the user who created it. You'll only see and manage the keys you created; teammates in the same organization no longer share each other's keys.
  • Reasoning model responses render fully: The playground and background jobs now display responses from reasoning models correctly, including when the model returns its output in the reasoning channel. Previously some reasoning-only responses appeared blank.
  • Accurate expiry warnings: API keys expiring soon now show the real remaining days ("1 day", "3 days", "7 days") instead of a fixed label.
  • Background jobs: Async inference jobs are more resilient: retries are now clearly signalled, and completed jobs are protected from late status updates. Prompt content is no longer written to job logs.
  • Streaming reasoning playground: Responses from reasoning models stream smoothly and display both the thinking process and final answer reliably.

v1.1.0 (2026-04-14)

Added

  • Background jobs: Submit long-running inference with background: true and poll /api/v1/jobs/{id} for the result. The legacy async: true field still works as an alias.
  • Reasoning effort control: Models that expose the reasoning_effort parameter now show a Low / Medium / High selector in the playground.
  • Streaming thinking display: When a reasoning model streams its chain-of-thought, the playground shows it as a separate panel above the response, visible token-by-token as the model thinks.

Improved

  • Real-time streaming: Chat completion responses now stream token-by-token through every layer of the platform. First tokens reach the playground in well under a second on supported models.
  • Usage history consolidates events that referenced a model by ID; totals now appear under the model's display name automatically.
  • Background job documentation clearly explains the background: true contract, the async: true alias, unsupported combinations (streaming, image generation, callbacks, some provider-backed models), and the 24-hour result retention window.
  • Playground layout no longer widens horizontally when long code blocks appear.
  • Authentication pages render correctly for icon-only customer logos.

Fixed

  • Rate-limit counting is now precise under heavy concurrent load; requests are no longer over- or under-counted.
  • Pricing displays consistently as "USD per 1M tokens" across the model catalog and admin forms.

v1.0.4 (2026-04-13)

Added

  • Custom date ranges on the Usage page now support hour and minute precision for fine-grained querying.
  • Platform branding supports a dedicated dark-mode logo variant that automatically swaps with your theme.

Improved

  • Background job documentation now clarifies background: true, the legacy async: true alias, unsupported combinations, and 24-hour result retention.
  • Usage trends and Excel exports now use a canonical reporting endpoint for consistent totals across all views.
  • Usage history exports correctly fetch all paginated records for large result sets.
  • Rate-limit enforcement is now handled centrally by the platform with improved consistency.
  • Platform stability is improved via deterministic database migration handling across all services.

v1.0.3 (2026-04-13)

New Features

  • Added Team Usage view on the Usage page. Organization owners and admins can now see every team member's requests, tokens, cost and share of the organization in one table, with full time-of-day filtering.
  • Added hour and minute precision to the custom date range picker. Investigate usage during a specific incident window (for example 14:30–16:00 today) instead of being limited to whole days.
  • Added a Today preset to the date range selector alongside 7D, 30D, 90D and Custom.

Improvements

  • Improved invite emails: administrator-initiated invitations now use a dedicated, cleaner subject line.
  • Improved email reliability across Gmail, Outlook desktop, Outlook web and Apple Mail by replacing gradient buttons with solid brand-color buttons that render consistently everywhere.
  • Improved invite experience: if too many emails have been sent to an address in a short window, the invite page now explains how long to wait before retrying.
  • Improved the models Excel export: internal infrastructure fields (engine type, VRAM estimate) are no longer included.
  • Improved the Organization page: labels now consistently say "Organization" rather than mixing in "Tenant".
  • Improved the dashboard, organization and usage popovers: date pickers and user menus now always anchor to the element you clicked instead of drifting off-screen on scrolled pages.
  • Improved accessibility: the theme toggle now uses an English, standards-friendly label.

Fixed

  • Fixed a case where the Team Usage breakdown table stayed empty for organizations with many members.
  • Fixed the custom date range picker layout on the Usage page so it no longer overflows the card or gets clipped by the sidebar.

Security

  • Improved the public models endpoint to strip internal engine metadata from the response payload.

v1.0.2 (2026-04-10)

New Features

  • Added CSV and JSON export for API keys, jobs, models, organization, and usage data
  • Added context window tracking in the playground with overflow handling
  • Added true CFG scale parameter for image generation models
  • Added spending limit email alerts: receive notifications at 80% and 90% of your daily limit

Improvements

  • Improved rate limit headers for better OpenAI SDK compatibility
  • Improved playground experience with async job status messages
  • Updated custom date range picker with cleaner overlay design
  • Added version indicator to sidebar

Fixed

  • Fixed image generation timeout for larger models
  • Removed unused cache analytics column from usage page

v1.0.1 (2026-04-08)

Improvements

  • Portal: Platform version is now displayed in the sidebar header for easy identification.

v1.0.0 (2026-04-08)

Initial release.