# How to Import API Keys in Bulk into FreeLLMAPI: 3 Methods Explained

> Bulk import API keys into FreeLLMAPI easily. Discover three methods: web dashboard, HTTP API, or custom script. Streamline your API key management now.

- Repository: [Tashfeen/freellmapi](https://github.com/tashfeenahmed/freellmapi)
- Tags: how-to-guide
- Published: 2026-08-28

---

**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.

1. Start FreeLLMAPI (default: `http://localhost:3001`)
2. Navigate to **Keys** → **Bulk import**
3. Paste your keys in `.env` format:

```bash
GROQ_API_KEY=gsk_test123
ANTHROPIC_API_KEY=sk-ant-test
OPENAI_API_KEY=sk-openai-test

```

4. Review the parsed preview—toggle individual rows on/off
5. Click **Import** to store keys encrypted in the SQLite database

The dashboard uses two parser utilities in [`server/src/lib/key-parser.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/key-parser.ts):
- `parseDotEnv()` — handles `KEY=value` line-by-line format
- `parseJson()` — 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`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/keys.ts) (lines 1223–1252).

### Request Format

```json
{
  "keys": [
    { "keyName": "GROQ_API_KEY", "keyValue": "gsk_test123" },
    { "keyName": "ANTHROPIC_API_KEY", "keyValue": "sk-ant-test" }
  ]
}

```

### cURL Example

```bash
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

```json
{
  "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

```javascript
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

```python
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`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/keys.ts) | Main route handler for `POST /api/keys/import-selected` |
| [`server/src/lib/key-parser.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/key-parser.ts) | DotEnv and JSON parsing utilities |
| [`server/src/__tests__/routes/keys.test.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/__tests__/routes/keys.test.ts) | Unit tests for import validation logic |
| [`docs/architecture.md`](https://github.com/tashfeenahmed/freellmapi/blob/main/docs/architecture.md) | Feature documentation mentioning bulk key import/export |

The route in [`keys.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/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 `.env` files
- **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 `.env` content 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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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.