Skip to main content
Use keys.updateKey to change what a key can do without issuing a new one. The key string stays the same, so your users keep working. Only keyId is required. For every other field:
  • Leave it out to keep the current value.
  • Send a value to replace it.
  • Send null to clear it, for example to remove an expiry, a refill schedule, or an identity link.
You need a root key with the permissions listed on this page. Create one in the dashboard under Settings > Root Keys. See Permission reference for every permission.
The root key needs api.*.update_key or api.<api_id>.update_key. Without it you get HTTP 403 err:unkey:authorization:insufficient_permissions. A keyId that doesn’t exist or belongs to another workspace returns HTTP 404 err:unkey:data:key_not_found. See Root key permissions.

Request fields

string
required
The key’s ID (key_...), not the key string. 3 to 255 characters matching ^[a-zA-Z0-9_]+$.
string | null
1 to 255 characters. null removes the name.
string | null
1 to 255 characters matching ^[a-zA-Z0-9_.-]+$. Moves the key to the identity with that externalId, creating the identity in the keyspace’s project if it doesn’t exist yet. An existing identity in a different project is rejected with HTTP 404 err:unkey:data:identity_not_found. null unlinks the key from its identity. See Identities.
object | null
JSON with at most 100 top-level properties. It replaces the old metadata rather than merging. null removes it. See Metadata and tags.
integer | null
Unix timestamp in milliseconds, at most 4102444800000 (1 January 2100). null makes the key permanent. A timestamp in the past is accepted and expires the key at once. See Key expiration.
object | null
credits.remaining (integer or null, 0 or more) and credits.refill (object or null). Unlike keys.createKey, neither is required, so you can change a schedule without resending the balance. See Credits and refill on update. See Credits and refill.
object[] | null
Up to 50 limits, each with name (3 to 128 characters), limit (1 or more), duration in milliseconds (1000 or more), and autoApply. The list replaces the key’s limits rather than adding to them. null or [] removes them all. See Key and identity rate limits.
boolean
false suspends the key and true restores it. Not nullable. See Disabling and deleting keys.
string[]
Up to 100 role names, each 1 to 128 characters. The list replaces the key’s roles. Not nullable, so send [] to detach them all.
string[]
Up to 1000 permission slugs, each 1 to 128 characters matching ^[a-zA-Z0-9_:\-\.\*]+$. The list replaces the key’s direct permissions. Not nullable, so send [] to detach them all.

Credits and refill on update

The balance is credits.remaining and the schedule is credits.refill. Clearing one sometimes clears the other: Removing the balance removes the schedule too. Removing the schedule keeps the balance, so you can stop a subscription from renewing without taking away credits the customer already paid for. A refill object has interval (daily or monthly) and amount (1 or more). refillDay (1 to 31) is for monthly only. Sending it with daily, or leaving it out with monthly, fails with HTTP 400 err:unkey:application:invalid_input. (keys.createKey ignores refillDay with daily, so a body that works for create can fail here.) To change only the balance, use keys.updateCredits.

Lists replace, they don’t merge

ratelimits, roles, and permissions are each the full list you want the key to end up with. Send every entry you want to keep, not just the new ones.
  • Rate limits are matched by name. A limit you send keeps its ID and gets the new values. A limit you leave out is deleted.
  • Roles must already exist. The first one that doesn’t fails the request with HTTP 404 err:unkey:data:role_not_found.
  • Permissions that don’t exist yet are created for you. This list only replaces the key’s direct permissions, not what its roles grant.
To add or remove one entry without resending the list, use keys.addPermissions, keys.removePermissions, keys.addRoles, or keys.removeRoles instead. Managing key permissions compares them.

Example

Move a key to the paid plan, extend it, and stop it expiring:

Response

The response has no key data. Use keys.getKey to read the result.

When the change takes effect

An update applies in full or not at all, so an error leaves the key as it was. Changes take about 10 seconds to reach verification, and a few verifications just after that can still see the old settings. A new credit balance applies right away. Verifying keys has the details. Each update writes a key.update audit event, plus a permission.create event for each permission it created.

What you can’t change

You can’t change apiId, prefix, byteLength, or recoverable after a key is created. To replace the key string while keeping the same configuration, see Rerolling keys. To start over, create a new key and delete the old one.
Last modified on September 29, 2026