What makes a good API key?
Written by Frank Fiegel on .
A customer sent me a support email saying that they were having trouble with their API key.
The first version of Glama API keys were just a random UUIDs, and the particular API key was: 05e3d22f-640b-4257-9325-8c2a8144639f
.
However, I couldn't find any information about the API key in our database, and with this being just a random UUID, there wasn't much to go on.
After a few back and forths, it turned out that they were referencing an API key for a deleted account. However, this interaction made me want to rethink our API key format.
What others are using?
The first thing I did was to look at the API keys of services that Glama is already using.
Here is a selection of API keys from various companies:
Obviously, the API keys were altered.
Anthropic API key:
OpenAI API key:
Fun fact: you can identify OpenAI API keys by the way they contain "T3BlbkFJ" (OpenAI
in Base64).
This makes it easy to detect them in a secret scanner for preventing leaks in repos without false positives.
Groq API key:
Perplexity API key:
Stripe API key:
From this exercise I learned that:
- Many API keys have a prefix that indicates the type of key (e.g.,
sk-
for secret keys in OpenAI,pk_
for public keys in Stripe,gsk_
for Groq,pplx-
for Perplexity). - Some keys also include suffixes that may indicate the environment (e.g.,
test
in Stripe's key). - Some keys are segmented by hyphens or underscores. Presumably, it's done not just for readability, but also used to encode data within the key that allows grouping of keys (e.g.,
api03
in Anthropic's key describes the API version). - Lengths vary significantly, but most are quite long (48+ characters).
Sentry API key
One interesting exception that caught my eye was the Sentry API key.
The key includes a Base64URL-encoded JSON object with the following structure:
Base64URL is a variant of Base64 encoding that is URL-safe and filename-safe. It uses '-' and '_' instead of '+' and '/' respectively, and omits padding characters. This makes it ideal for use in URLs and filenames without requiring additional encoding.
The payload is a JSON object with the following structure:
iat
here is the date issued at (iat
stands for "issued at").
The thing that I like about the Sentry's format is that the key itself encodes information that is useful for troubleshooting purposes.
Designing the perfect API key
Based on the above, here is my design for the API key format:
- The key should have a prefix that describes the workspace that owns the key.
- The key should have a stable fragment that can be used as public key identifier.
- The key itself should encode information that is useful for troubleshooting purposes (e.g., user ID).
Which, in case of Glama, translates to:
glama_
prefix- public key identifier
- user ID
- secret (UUID)
This translates to:
Here is an example:
which can be decoded to:
This API key has the benefit that:
- Can be identified as belonging to Glama.
- Can be uniquely identified by the unique public identifier of the API key.
- This would be the ID that identifies the key in the dashboard.
- Can be used to identify the user by decoding the Base64URL payload.
- Can be expanded to include more information over time (such as the API endpoint, like in the case of Sentry).
The reason for Base64URL encoding the key is that it allows us to expand the information that is encoded in the key without changing the format of the key itself.
On the server side, I decode the payload and use the information to identify the user.
Conclusion
The API key could be as simple as a random UUID, but adding a prefix and encoding the payload enables greater usability and troubleshooting.
Written by Frank Fiegel (@punkpeye)