keys.verifyKey instead of looking keys up in your own table.
After the move, you no longer store plaintext keys or write the hash comparison. If you switch those checks over too, you also stop running your own rate-limit counters and monthly usage counters. You still run your API, unless you deploy it on Compute, and you still return 401 and 429 to your users. Unkey stores a SHA-256 hash of the full key, base64 encoded, and compares that on verification. See How Unkey stores API keys.
Agree the hash format with Unkey before the import. The two formats are below.
Get a migration ID
Email support@unkey.com with your workspace ID, the system the keys come from, and how they’re hashed. Support sends amigrationId. Two hash formats work today.
Keys hashed any other way, such as bcrypt or a salted hash, can’t be imported from the hash alone. Tell support, and the migration needs another plan.
Hash the keys yourself
Forsha256, this is the same function Unkey uses, so a key hashed this way works exactly like one Unkey created.
hash.ts
Create a root key with the permissions listed on this page under Root Keys in the dashboard sidebar. CLI commands can instead use a session from unkey login with the required permissions. See Permission reference for every permission.
keys.migrateKeys needs api.*.create_key or api.<api_id>.create_key. Verifying afterwards needs the usual api.*.verify_key. See Root key permissions.
Import the hashes
string
required
The identifier from support, 3 to 255 characters. An unknown ID returns HTTP 404
err:unkey:data:migration_not_found.string
required
The keyspace to import into.
object[]
required
At least one entry. Each has a required
hash (3 or more characters, in your migration’s format) and the same optional fields as keys.createKey: name, externalId, meta, roles (up to 100), permissions (up to 1000), expires, enabled (default true), credits, and ratelimits (up to 50). The rules match Creating keys.Response
The response is HTTP 200 even when some hashes fail. A hash that already exists anywhere in Unkey, not just in your workspace, is skipped and listed underfailed. Every other key is created and returned with its new keyId. Store it next to your own record of the key.
migrated against your export after each one.
Switch verification over
Point your backend atkeys.verifyKey. For the sha256 algorithm nothing else changes. For the prefixed-api-key algorithm, include the migrationId in every verification during the roll-out:
migrationId, it works with or without the field. A key that hasn’t been verified yet still needs it and returns NOT_FOUND without it, so keep sending migrationId until the fallback below goes quiet.
Run both systems during the switch
Verify against Unkey first. If a key comes backNOT_FOUND, check your old system and log it. Remove the fallback when the log goes quiet. Create new keys with keys.createKey so new users are never in the old system.