Skip to main content
Credits cap how much a key can be used in total. (Rate limits cap how often.) A key starts with a balance, and each verification spends some of it. When the balance can’t cover a request, the key stops working until you add more or a scheduled refill restores it. Use credits for “1,000 requests included” plans, trials, and pay-per-use APIs.

How spending works

A key has credits when credits.remaining is a number. If it’s null or missing, the key is unlimited. Each keys.verifyKey call costs 1 unless the request sets credits.cost, any integer from 0 to 1,000,000,000,000. Credits are checked last, so a key that fails any other check (disabled, expired, rate limited, missing permissions) doesn’t lose credits. What happens next depends on the balance:
  • Enough credits. The cost is deducted and the response’s credits field shows the new balance.
  • Not enough. Nothing is deducted, the verification fails with code: USAGE_EXCEEDED, and credits shows the unchanged balance.
The balance never goes below zero. A cost of 0 checks the key without spending anything, so you can check a key or read its metadata for free.
Verifications in every region spend from the same balance, so no spend is lost.

Add credits to a key

Set credits.remaining when creating the key, or later with keys.updateKey.
integer | null
Starting balance, 0 or more. On keys.updateKey, null removes the limit entirely and also clears any refill schedule. On keys.createKey, null isn’t allowed, so omit credits instead.

Refill on a schedule

A refill resets the balance to a fixed amount on a schedule. It replaces the balance rather than adding to it: a key with 50 credits left and a refill of 1000 has 1000 afterward, not 1050. You must set credits.remaining in the same request.
string
required
daily or monthly.
integer
required
The balance after each refill, 1 or more.
integer
1 to 31. Required when interval is monthly. Leaving it out fails with HTTP 400 err:unkey:application:invalid_input. With daily, keys.updateKey rejects it with the same error and keys.createKey ignores it. If the month is shorter, the refill runs on its last day, so 31 works in February.
Refills run once a day at 00:00 UTC, whatever your customer’s time zone. Daily keys refill every day, and monthly keys refill on their refillDay. A key that’s already at or above its amount is left alone. To stop refilling but keep the current balance, send credits.refill: null on keys.updateKey. To change the schedule, send the whole refill object again.

Change a balance directly

Use keys.updateCredits for top-ups, purchases, and refunds. It changes the balance and leaves the refill schedule alone.
string
required
The key to change.
string
required
set replaces the balance with value, increment adds value, and decrement subtracts value and clamps at zero.
integer | null
0 or more. Required for increment and decrement. With set, null makes the key unlimited.
On a key with unlimited credits, increment and decrement fail with HTTP 400 err:unkey:application:invalid_input. To give an unlimited key a quota, send set first.
The root key needs api.*.update_key or api.<api_id>.update_key for both keys.updateKey and keys.updateCredits. See Root key permissions.

Credits vs rate limits

Use both when you sell a quota and also want burst protection. The rate limit stops a client from burning the quota in a second, and credits enforce the quota. See Key and identity rate limits.
Last modified on September 29, 2026