> ## Documentation Index
> Fetch the complete documentation index at: https://unkey.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Unkey is two separate products. Compute builds, deploys, and runs apps behind a gateway. API Management issues API keys, enforces rate limits, manages identities and permissions, and reports usage. Say which product a page belongs to; a reader can use either without the other.
> Every Unkey API endpoint is an HTTP POST to https://api.unkey.com/v2/{service}.{procedure} with a root key in the Authorization: Bearer header. Root keys are workspace scoped.
> Error codes have the form err:{system}:{category}:{specific} and each has a page at /errors/{system}/{category}/{specific}.
> The word environment means production or preview in Compute. Rate limiting has four meanings on this site; the glossary lists them.

# Key storage

> Know why Unkey shows a key only once and when you can get it back.

export const ProductLink = ({product, href, title, children}) => {
  const productNames = {
    compute: "Compute",
    "api-management": "API Management",
    platform: "Platform"
  };
  return <div className="card unkey-product-card" data-card-href={href}>
      <div data-component-part="card-content-container">
        <h2 data-component-part="card-title">
          <a className="unkey-product-card-title" href={href}>
            {title}
          </a>
        </h2>
        <div data-component-part="card-content">
          <strong>{productNames[product]} docs.</strong> {children}
        </div>
      </div>
    </div>;
};

<ProductLink product="api-management" href="/docs/api-management/keys/recoverable-keys" title="Keyspaces and recoverable keys">
  Keyspaces, `keys.createKey`, and recoverable keys are part of API Management. Here we only cover how keys are stored.
</ProductLink>

## A key is shown once

When you create an API key or a root key, you see it once, in the create response or the dashboard dialog. We keep only a SHA-256 hash of it. A leaked copy of our database doesn't yield working keys, and we can't show you a key again unless it's a recoverable key.

Moving keys from another system? [Migrating keys](/docs/api-management/keys/migrating-keys) lists the hash formats we accept.

## Recoverable keys

A recoverable key is one you can show again later. To create one:

1. Ask [support@unkey.com](mailto:support@unkey.com) to turn on encrypted storage for the keyspace. It's off by default and set per keyspace.
2. Create the key with `recoverable: true`, using a root key with the encrypt permission for that keyspace.

We keep an encrypted copy next to the hash. A root key with the decrypt permission can read the key back later.

Without encrypted storage, creating a recoverable key fails with `err:unkey:application:precondition_failed` and "This API does not support key encryption."

This weakens the guarantee above: anyone with a root key that has decrypt can read the key, so grant decrypt narrowly.

## What you should do

Copy a non-recoverable key when it's returned. That's the only time you'll see it. If you lose a key, create a new one and delete the old one. The same goes for root keys. Use a separate root key per service so a leak affects as little as possible. If a root key lands in a public repo, [GitHub secret scanning](/docs/platform/security/github-secret-scanning) tells you, but it doesn't disable the key for you.
