How to Import API Keys in Bulk into FreeLLMAPI: 3 Methods Explained
You can bulk-import API keys into FreeLLMAPI using the web dashboard (paste .env format), the HTTP API endpoint /api/keys/import-selected, or a custom script that calls the API.
FreeLLMAPI is an open-source LLM router that aggregates free-tier APIs from multiple providers. Configuring many provider keys at once is essential for production deployments. This guide covers three verified methods to import API keys in bulk, with implementation details drawn directly from the tashfeenahmed/freellmapi source code.
Method 1: Dashboard UI Bulk Import
The simplest approach uses the built-in web interface. No coding required.
- Start FreeLLMAPI (default:
http://localhost:3001) - Navigate to Keys → Bulk import
- Paste your keys in
.envformat:
GROQ_API_KEY=gsk_test123
ANTHROPIC_API_KEY=sk-ant-test
OPENAI_API_KEY=sk-openai-test
- Review the parsed preview—toggle individual rows on/off
- Click Import to store keys encrypted in the SQLite database
The dashboard uses two parser utilities in server/src/lib/key-parser.ts:
parseDotEnv()— handlesKEY=valueline-by-line formatparseJson()— handles JSON array input
These parsers normalize input before the UI submits to the server.
Method 2: HTTP API Endpoint
For automation, call the bulk-import API directly. The route is implemented in server/src/routes/keys.ts (lines 1223–1252).
Request Format
{
"keys": [
{ "keyName": "GROQ_API_KEY", "keyValue": "gsk_test123" },
{ "keyName": "ANTHROPIC_API_KEY", "keyValue": "sk-ant-test" }
]
}
cURL Example
curl -X POST http://localhost:3001/api/keys/import-selected \
-H "Content-Type: application/json" \
-d '{
"keys": [
{"keyName":"GROQ_API_KEY","keyValue":"gsk_test123"},
{"keyName":"ANTHROPIC_API_KEY","keyValue":"sk-ant-test"}
]
}'
Response Structure
{
"imported": [
{ "keyName": "GROQ_API_KEY", "platform": "groq" },
{ "keyName": "ANTHROPIC_API_KEY", "platform": "anthropic" }
],
"skipped": []
}
The server performs three operations on each entry:
- Validation — checks key format against provider patterns
- Deduplication — skips keys already in the database
- Encryption — stores values encrypted before database write
Method 3: Programmatic Script
Integrate bulk import into your deployment pipeline. Since FreeLLMAPI lacks a dedicated CLI command for bulk import, scripts must call the HTTP endpoint.
Node.js Example
import fetch from 'node-fetch';
async function bulkImportApiKeys(keys) {
const response = await fetch('http://localhost:3001/api/keys/import-selected', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ keys })
});
if (!response.ok) {
throw new Error(`Import failed: ${response.status}`);
}
const result = await response.json();
console.log(`Imported: ${result.imported.length}, Skipped: ${result.skipped.length}`);
return result;
}
// Execute
bulkImportApiKeys([
{ keyName: 'GROQ_API_KEY', keyValue: 'gsk_test123' },
{ keyName: 'ANTHROPIC_API_KEY', keyValue: 'sk-ant-test' }
]);
Python Example
import requests
keys = [
{"keyName": "GROQ_API_KEY", "keyValue": "gsk_test123"},
{"keyName": "ANTHROPIC_API_KEY", "keyValue": "sk-ant-test"}
]
response = requests.post(
"http://localhost:3001/api/keys/import-selected",
json={"keys": keys}
)
result = response.json()
print(f"Imported: {len(result['imported'])}, Skipped: {len(result['skipped'])}")
Key Implementation Files
Understanding the source structure helps with troubleshooting:
| File | Purpose |
|---|---|
server/src/routes/keys.ts |
Main route handler for POST /api/keys/import-selected |
server/src/lib/key-parser.ts |
DotEnv and JSON parsing utilities |
server/src/__tests__/routes/keys.test.ts |
Unit tests for import validation logic |
docs/architecture.md |
Feature documentation mentioning bulk key import/export |
The route in keys.ts handles both dashboard submissions and direct API calls. The parser module separates concerns: input normalization happens before database operations, keeping the route handler clean.
Format Recommendations
FreeLLMAPI accepts two input formats. Choose based on your source:
- DotEnv format — copy directly from existing
.envfiles - JSON arrays — better for programmatic generation
Mixed formats in a single request are not supported. Convert separately, or use the dashboard UI which auto-detects format.
Summary
- Dashboard UI: Fastest for one-time setup; paste
.envcontent directly - HTTP API: Best for CI/CD pipelines and infrastructure-as-code
- Custom scripts: Required for CLI automation; call the endpoint with
curl, Node.js, Python, or any HTTP client - All methods use the same validation, deduplication, and encryption pipeline in
server/src/routes/keys.ts
Frequently Asked Questions
What happens if I import a duplicate key?
The import process checks existing keys before insertion. Duplicates appear in the skipped array of the response, and the database remains unchanged for those entries. No error is thrown—imports are partially successful by design.
Is there a rate limit on bulk imports?
The source code does not implement specific rate limiting on the /import-selected endpoint. However, large payloads may hit general request size limits. Batch imports of 50–100 keys per request for reliable operation.
Can I import keys from a JSON file directly?
Not through a dedicated file upload. Convert your JSON file contents to either: (a) the dashboard's expected format by copying the array, or (b) the API's JSON body structure using a script that reads the file and submits via HTTP.
Are imported keys encrypted immediately?
Yes. According to the implementation in server/src/routes/keys.ts, all keyValue fields are encrypted before SQLite storage. The encryption uses the server's configured cipher—keys are never stored in plaintext.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →