本服务面向非中国大陆地区 · ZetaAPI.AI 的网站与控制台主要面向非中国大陆市场,注册与开通功能在你当前地区不可用。
Back to blog
Product 2026-03-27 5 min

Why we built the compensation rules into the product instead of hiding them in support scripts

Most API SLAs are legal text nobody reads. We turned incident compensation into productized public rules (automation rolling out; currently claim-based).

Rollout status (updated 2026-07-09): This post describes the full design of the compensation system. The rules and algorithm apply as written; compensation is currently claim-based — contact support to file, and we settle to your balance after a manual review against the published algorithm (how to file). Automated monitoring is live; automatic computation, crediting and the monthly email are rolling out in stages — until then, descriptions of fully automated crediting and monthly emails refer to the target state.

What SLAs usually look like

Read the SLA text of ten mainstream API services and they all look nearly identical:

  • An availability commitment (commonly 99.9% / 99.95%)
  • A table mapping downtime to a compensation percentage (5%–50% of the monthly fee)
  • A clause requiring “the user to actively file a claim with evidence”
  • A “force majeure excepted” clause

How often are these texts actually used? We asked a few peers: nearly never. A user’s first reaction to a problem is to switch providers, not to read the SLA.

The reason is simple: the cost of the claim process exceeds the compensation you can get. Log in, file a ticket, upload screenshots, wait 7 business days for review, and maybe end up with a 15%-of-monthly-fee credit — net-negative once you count your time.

What we did

We turned compensation from “a document you go dig up when something breaks” into automatic logic inside the product — rules, computation and crediting require no action from you.

1. Calendar month + SKU group + three compensation tiers

After each calendar month (UTC+8) closes, we compute compensation independently per SKU group for that month (Claude / Claude Code / GPT / Gemini / Qwen / a group of Chinese models at 50% off / Doubao) based on availability:

  • ≥ 99% — no compensation
  • 98% – 99% — 2% of that SKU’s monthly order amount
  • 95% – 98% — 5%
  • < 95% — 10% (the monthly cap is also 10%)

Tiers computed independently means: if this month Claude is 96% / GPT 99.5% / Gemini 100%, only the Claude portion is compensated at 5%; the other SKUs are untouched. Why not a continuous formula or finer intermediate tiers? Because customers and BD both need to do the math in their heads. Explaining “your 96.3% maps to 5pp + 0.3 × X” to a customer every time is a waste of time. Three step-changes also reinforce the “hold 95%” target line — oncall themselves know it’s the floor.

2. Auto-settled at month-end — you don’t have to spot the problem

After the month-end run, at 9am on the 3rd of the next month every affected customer gets an email: monthly availability per SKU group, the compensation amount, and the calculation breakdown. The amount first lands in a holding account — you can see it in the email and the dashboard, but can’t use it yet. During a 7-day appeal window (the 3rd–10th of the next month) either you or we can dispute the calculation; when the window closes with no upheld appeal, the amount automatically becomes usable balance. Past the window, it’s accepted by default. Any single compensation ≥ ¥5,000 is first frozen for 24 hours for ops review (to guard against a dashboard bug over-paying), then enters the holding account once review passes.

Tiny samples don’t trigger compensation: under 100 monthly calls for a single SKU, or under 1,000 monthly platform-wide samples for an SKU, doesn’t trigger compensation that month — a “94%” computed from 50 calls is too noisy to base compensation on. SLA coverage is unchanged; there just isn’t a computable payout in that case.

3. The failure definition only counts hard errors we’re responsible for — and there’s tension here

Only these three classes of request count toward the “unavailable” numerator:

  • Upstream server returns 5xx (500/502/503/504)
  • Upstream doesn’t return the first byte within 60 seconds (timeout)
  • Our gateway 5xx (routing / billing layer crash)

Active rate limiting, upstream 401 / 429, client 4xx, and balance exhaustion don’t count. This is a contentious choice, and we have to be clear about the tension:

A client can hit “it clearly doesn’t work but the SLA number is still 99%” — e.g. your single key tripped a QPS limit (we return 429, asking you to retry), or an upstream account token expired and we’re switching. What you feel is “the service is unstable,” but the SLA number doesn’t move.

We chose this definition not to protect the number, but because only hard errors on our gateway + the upstream server are what the SLA semantics can be responsible for. Rate limiting is a product policy (documented in the integration docs); client 4xx is a request-layer error; folding these into availability would make the SLA a number even we can’t interpret. For rate-limit / 401 / 429 problems that really do block your code, our policy is oncall watching alerts + a 30-second channel switch, not waiting on your ticket.

4. Maintenance-window deductions are constrained and can’t be used to dress up the number

Planned maintenance can be deducted from the denominator, but only if all three conditions hold: ≥ 7 days’ notice + ≤ 4h per occurrence + ≤ 8h cumulative per month. Anything beyond 8h goes back into the denominator as a failure; upstream-initiated maintenance (even pre-announced) is not deductible — that’s an upstream problem, not ours. This rule is written tight on purpose, to stop ops from turning maintenance windows into an SLA beautifier.

What it costs us

  • Financial forecasting has to be re-modeled — compensation is a real cost now, no longer “a promise that won’t be honored.” We built a compensation-reserve rate from historical failure data, about 0.4% of revenue.
  • The monitoring-accuracy bar rises — misjudge a failure and you’re giving users money. Our failure-detection algorithm went through two-person code review and ran in shadow for a month before launch.
  • Failure narratives can’t be fudged — you used to be able to say “occasional fluctuation”; now the bill spells out the compensation amount in black and white, and anything less than honest is a self-own.

Why we’re writing this now

Talking with a few teams recently, we found expectations of API SLAs are already very low — “it’s written but useless anyway.” What we want to say is: an SLA doesn’t have to be legal text; it can be the product itself. This isn’t us being clever; the industry bar is just too low.

If this article makes you go “oh, you can do it like that,” that’s enough.

Related posts