Credits, keys, and what a call costs
The hosted API is prepaid. You buy input tokens, or you use the monthly grant, and each decide call draws that balance down. Structured output is free. This page is the meter this website implements. The live pack table is on pricing.
The unit
A call is billed on input tokens only, in units of 1,000. Each unit is $0.0004. A call costs at least one unit, even when the text is short. Output tokens reported by the upstream are not billed. That is why a response with several choice, score, and noul fields does not add a second charge. The price is for the decision, not for a chat completion and a parser after it.
Before the upstream is called, the server estimates tokens from the size of the JSON, about one token per four characters, and holds that many units. After the call, it settles on usage.input_tokens from the upstream. If the real cost is lower, the difference is returned to the balance. If the call errors after the hold, the hold is refunded. If the balance cannot cover the estimate, the route returns 402 and does not call the upstream. The error text points at the pricing page.
Anonymous calls are the exception to the hold. They do not draw a balance. They consume the free-run counter instead. The default is one successful anonymous decide, from ANON_FREE_RUNS. The counter is a cookie named laya_anon. It is not tied to a Google account. When the allowance is used, the next anonymous call returns 401 and asks for a key or a sign-in. Anonymous attempts are also limited to 20 a minute, so a loop cannot burn the single free run into a retry storm.
Google sign-in and the monthly grant
There is no email and password form. The account page signs you in with Google. We store the email, name, profile image URL, and Google subject so the keys and the balance stay on that account. We do not receive the Google password. Details are in the privacy policy.
The first successful Google registration starts 10k_monthly: 10,000 input tokens each UTC calendar month. That is about 10 typical decide calls, because a typical call is one billing unit. The grant is applied again in later months when the account is used. Prepaid packs stack on top of the grant. They do not replace it. The size can be changed on the server with SIGNUP_GIFT_TOKENS. The account page states the grant that this deploy is actually giving.
A new account starts at 30 requests per minute. That ceiling is separate from the token balance. You can have tokens left and still receive 429 if you exceed the rate, or exceed the burn caps: 5,000,000 input tokens in a rolling hour, and 80,000,000 in a rolling day. Those caps exist so one key cannot drain a large balance in a tight loop without the rate check noticing.
Packs
Five one-time packs are defined. Spark is $8 and sets the rate ceiling to 40 requests per minute if the account is below that. Bench is $24 at 90 RPM. Runway is $60 at 140 RPM. Floor is $140 at 220 RPM. Plant is $320 at 360 RPM. Buying a pack raises the ceiling when the pack's rate is higher. It never lowers a ceiling you already have. At $0.0004 per 1,000 input tokens, one dollar is 2,500 of those units. An $8 pack is 20,000 units, which is 20 million input tokens, if every call is a single unit. Larger requests consume more units. The pricing page prints the token count and the typical-decide count from this same formula, so use that table when you plan a budget.
Unused balance is not a bank deposit. The terms say that directly. The balance is prepaid credit for input tokens on this API. It is not a stored card, and it is not transferable to the local Apache-2.0 package. Running Router() on your own machine does not draw this balance, and buying a pack does not change what pip install laya scores.
Checkout uses Creem when CREEM_ENABLED is true and CREEM_API_KEY is set. You must be signed in with Google before a buy starts. The button creates a checkout and sends you to Creem. Coming back to /api/payment/callback does not add credits. A paid checkout.completed notification on POST /api/payment/notify/creem does, after the signature matches the signing secret. If Creem is off, the buy buttons stay visible and POST /api/checkout returns 503. The status page shows whether Creem is on. Stripe is used only when DEFAULT_PAYMENT_PROVIDER is stripe. We store the order id and the pack. We do not store the card number.
Keys
Create a key on the account page after sign-in. The secret starts with laya_ and is shown once. After that the page lists a prefix, the first twelve characters, plus the name you gave the key and the last time it was used. The database stores a SHA-256 hash. A request sends Authorization: Bearer laya_…. A key that does not match the hash, or a key that was revoked, returns 401 with code invalid_key. A bearer token that does not even have the laya_ prefix returns the same status with a message that keys use that prefix.
You are responsible for calls made with a key you created. If a key leaks, revoke it on the account page before you write to anyone. Revoking stops further calls. It does not refund calls that already succeeded. A signed-in browser session can call decide without a key. That session bills the same balance and the same rate limit. Use a key from a worker. Use the session from the playground. Do not put the secret in a page, a ticket, or an email to the contact address.
The usage list on the account page is the ledger: route, input tokens, cost, and time. It does not include the prompt. If you need to debug a bad label, keep the request in your own logs. We will not have the ticket text to replay. POST /v1/gate does not appear as a billed row. The gate does not spend tokens and does not require a key.
What a worker should do with a 401 or 402
Treat 401 as an auth problem, not as a transient upstream failure. Refreshing the same anonymous cookie will not create a second free run. Create a key, or sign in. Treat 402 as an empty balance. The monthly grant, if it has not been applied yet this UTC month, is applied when the account is resolved for a keyed or signed-in call. It is not applied to anonymous calls. If the grant is already on the account and the balance is still too low, buy a pack. Do not retry a 402 in a loop. Each attempt still passes the rate limiter.
Treat 429 as a pause. The message names the account's requests-per-minute ceiling when that is the reason. The hourly and daily caps use a different message. Back off. A 503 means this deploy has no inference key. The status page is the place to confirm that. A 504 means the upstream did not answer within 120 seconds. The hold for a failed call is refunded, so a timeout should not leave the estimate stuck on the balance.
The request shape those errors belong to is in the decide API guide. A worked support ticket, from the tool fields through a gate, is in the support-triage guide.