API Reference: API Keys
Relevant source files
The following files were used as context for generating this wiki page:The API Key management system provides a secure way for users to store and manage their API keys for various AI providers (OpenAI, Anthropic, Google Gemini). These keys are essential for using the core resume enhancement features of the application. The system supports two modes: a "Full Mode" for authenticated users, which stores encrypted keys in the database, and a "Light Mode" for unauthenticated users, which stores keys in the browser's local storage.
This document details the database schema, security measures, and RESTful API endpoints used for managing user API keys in the full, database-backed mode. For information on the browser-based storage, see the Light Mode section.
Architecture Overview
The API Key management system involves a frontend component (ApiKeyManager), a set of API endpoints, an encryption utility, and the database. When a user adds a key, the frontend sends it to the API, which encrypts the key before persisting it in the UserApiKey table. When an enhancement is requested, the key is retrieved, decrypted, and used to call the external AI provider.
The following diagram illustrates the high-level architecture for creating a new API key.
Database Schema
The UserApiKey model stores the user's API keys. Each user can have one key per provider, enforced by a unique constraint on userId and provider.
Sources: schema.prisma:103-116
ER Diagram
This diagram shows the relationship between the User and UserApiKey models.
Sources: schema.prisma:40-52, schema.prisma:103-116
UserApiKey Model
The table below describes the fields in the UserApiKey model.
| Field | Type | Description | Constraints / Default |
|---|---|---|---|
id | String | Unique identifier for the API key entry. | @id @default(cuid()) |
userId | String | Foreign key linking to the User model. | Relation to User.id |
provider | String | The AI provider (e.g., 'openai', 'anthropic', 'gemini'). | |
keyName | String | A user-defined name for the key. | |
encryptedKey | String | The encrypted API key. | |
defaultModel | String | The default model to use for this provider (e.g., 'gpt-4o-mini'). | @default("gpt-4o-mini") |
isActive | Boolean | Indicates if the key is currently active. | @default(true) |
createdAt | DateTime | Timestamp of when the key was created. | @default(now()) |
updatedAt | DateTime | Timestamp of the last update. | @updatedAt |
@@unique([userId, provider]) |
Sources: schema.prisma:103-116
Security: API Key Encryption
API keys are always encrypted before being stored in the database to prevent exposure. The encryption and decryption processes use the crypto module from Node.js with the aes-256-gcm algorithm. A 32-character ENCRYPTION_KEY must be set as an environment variable.
The encryptApiKey function is called before saving a key to the database. The decryptApiKey function is used when an API key is needed to make a call to an external AI service, such as during resume enhancement.
Sources: lib/crypto.ts, api/api-keys/route.ts:101, api/enhance-resume/[id]/route.ts:208
Encryption Flow
The following sequence diagram shows how an API key is encrypted and stored when a user submits it.
API Endpoints
The following endpoints are available for managing API keys for authenticated users. All endpoints require a valid user session.
Sources: api/api-keys/route.ts, api/api-keys/[id]/route.ts
List API Keys
GET /api/api-keys- Description: Fetches a list of all API keys for the authenticated user. The encrypted key itself is not returned.
- Authentication: Required (User session).
- Response (200 OK):
{ "apiKeys": [ { "id": "clx...", "provider": "openai", "keyName": "My OpenAI Key", "defaultModel": "gpt-4o-mini", "isActive": true, "createdAt": "2023-10-27T10:00:00.000Z" } ] }
Sources: api/api-keys/route.ts:10-43
Add a new API Key
POST /api/api-keys- Description: Adds a new API key for a specific provider. The key is encrypted before storage. A user can only have one key per provider.
- Authentication: Required (User session).
- Request Body:
| Parameter | Type | Description | Required |
|---|---|---|---|
provider | string | 'openai', 'anthropic', or 'gemini' | Yes |
keyName | string | A user-friendly name for the key. | Yes |
apiKey | string | The plaintext API key from the provider. | Yes |
defaultModel | string | The default model to use for this key. | Yes |
- Response (200 OK): Returns the newly created API key object (without the plaintext key).
- Error Responses:
400 Bad Request: If required fields are missing or if a key for that provider already exists.401 Unauthorized: If the user is not signed in.500 Internal Server Error: If encryption or database operation fails.
Sources: api/api-keys/route.ts:45-149
Delete an API Key
DELETE /api/api-keys/[id]- Description: Deletes a specific API key by its ID.
- Authentication: Required (User session).
- URL Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | The ID of the UserApiKey entry to delete. |
- Response (200 OK):
{ "message": "API key deleted successfully" } - Error Responses:
401 Unauthorized: If the user is not signed in.404 Not Found: If the API key does not exist or does not belong to the user.500 Internal Server Error: If the database operation fails.
Sources: api/api-keys/[id]/route.ts
Light Mode vs. Full Mode
The application offers two modes for API key management, catering to both registered and guest users.
Full Mode (Authenticated Users)
- Component:
api-keys/_components/api-key-manager.tsx - Storage: Securely in the PostgreSQL database via the
/api/api-keysendpoints. - Persistence: Keys are tied to the user's account and are available across devices and sessions.
- Security: Keys are encrypted at rest using
AES-256-GCM.
Sources: api-keys/page.tsx, api-keys/_components/api-key-manager.tsx
Light Mode (Unauthenticated Users)
- Component:
api-keys-light/page.tsx - Storage: In the browser's
localStorage. - Persistence: Keys are only stored on the current device and browser. They are lost if browser data is cleared.
- Security: Keys are stored in plaintext in
localStorage, which is less secure than the database method. An alert in the UI warns the user about this. - Implementation: Uses the
localApiKeyStorageutility to interact withlocalStorage.
Sources: api-keys-light/page.tsx:1-100, lib/api-key-storage.ts
Supported Providers
Users can add API keys for the following AI providers. The frontend components provide links to each provider's API key generation page.
| Provider | Value | Description |
|---|---|---|
| OpenAI | openai | GPT models for resume enhancement |
| Anthropic Claude | anthropic | Claude models for professional writing |
| Google Gemini | gemini | Gemini models for comprehensive analysis |
Sources: api-keys/_components/api-key-manager.tsx:40-58, api-keys-light/page.tsx:20-38